Пример #1
0
        public async Task <IActionResult> Exchange(OpenIdConnectRequest request)
        {
            if (request.IsPasswordGrantType())
            {
                var user = await _userManager.FindByNameAsync(request.Username);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                // Ensure the user is allowed to sign in.
                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in."
                    }));
                }

                // Reject the token request if two-factor authentication has been enabled by the user.
                if (_userManager.SupportsUserTwoFactor && await _userManager.GetTwoFactorEnabledAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in."
                    }));
                }

                // Ensure the user is not already locked out.
                if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                // Ensure the password is valid.
                if (!await _userManager.CheckPasswordAsync(user, request.Password))
                {
                    if (_userManager.SupportsUserLockout)
                    {
                        await _userManager.AccessFailedAsync(user);
                    }

                    return(BadRequest(new OpenIdConnectResponse {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                if (_userManager.SupportsUserLockout)
                {
                    await _userManager.ResetAccessFailedCountAsync(user);
                }

                // Create a new authentication ticket.
                var ticket = await CreateTicketAsync(request, user);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            return(BadRequest(new OpenIdConnectResponse {
                Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                ErrorDescription = "The specified grant type is not supported."
            }));
        }
Пример #2
0
        public async Task <IActionResult> Exchange(OpenIdConnectRequest oIdRequest)
        {
            if (oIdRequest.IsPasswordGrantType())
            {
                ApplicationUser user = await _userManager.FindByEmailAsync(oIdRequest.Username) ?? await _userManager.FindByNameAsync(oIdRequest.Username);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "Please check that your email and password is correct"
                    }));
                }

                // Ensure the user is enabled.
                if (!user.IsEnabled)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user account is disabled"
                    }));
                }


                // Validate the username/password parameters and ensure the account is not locked out.
                Microsoft.AspNetCore.Identity.SignInResult result = await _signInManager.CheckPasswordSignInAsync(user, oIdRequest.Password, true);

                // Ensure the user is not already locked out.
                if (result.IsLockedOut)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user account has been suspended"
                    }));
                }

                // Reject the token request if two-factor authentication has been enabled by the user.
                if (result.RequiresTwoFactor)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "Invalid login procedure"
                    }));
                }

                // Ensure the user is allowed to sign in.
                if (result.IsNotAllowed)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in"
                    }));
                }

                if (!result.Succeeded)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "Please check that your email and password is correct"
                    }));
                }



                // Create a new authentication ticket.
                AuthenticationTicket ticket = await CreateTicketAsync(oIdRequest, user);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            else if (oIdRequest.IsRefreshTokenGrantType())
            {
                // Retrieve the claims principal stored in the refresh token.
                AuthenticateResult info = await HttpContext.AuthenticateAsync(OpenIddictServerDefaults.AuthenticationScheme);

                // Retrieve the user profile corresponding to the refresh token.
                // Note: if you want to automatically invalidate the refresh token
                // when the user password/roles change, use the following line instead:
                // var user = _signInManager.ValidateSecurityStampAsync(info.Principal);
                ApplicationUser user = await _userManager.GetUserAsync(info.Principal);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The refresh token is no longer valid"
                    }));
                }

                // Ensure the user is still allowed to sign in.
                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The user is no longer allowed to sign in"
                    }));
                }

                // Create a new authentication ticket, but reuse the properties stored
                // in the refresh token, including the scopes originally granted.
                AuthenticationTicket ticket = await CreateTicketAsync(oIdRequest, user);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            return(BadRequest(new OpenIdConnectResponse
            {
                Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                ErrorDescription = "The specified grant type is not supported"
            }));
        }
        public async Task <IActionResult> Exchange(OpenIdConnectRequest request)
        {
            Debug.Assert(request.IsTokenRequest(),
                         "The OpenIddict binder for ASP.NET Core MVC is not registered. " +
                         "Make sure services.AddOpenIddict().AddMvcBinders() is correctly called.");

            if (request.IsPasswordGrantType())
            {
                var user = await _userManager.FindByNameAsync(request.Username);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                // Ensure the user is allowed to sign in.
                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in."
                    }));
                }

                // Reject the token request if two-factor authentication has been enabled by the user.
                if (_userManager.SupportsUserTwoFactor && await _userManager.GetTwoFactorEnabledAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in."
                    }));
                }

                // Ensure the user is not already locked out.
                if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                // Ensure the password is valid.
                if (!await _userManager.CheckPasswordAsync(user, request.Password))
                {
                    if (_userManager.SupportsUserLockout)
                    {
                        await _userManager.AccessFailedAsync(user);
                    }

                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                if (_userManager.SupportsUserLockout)
                {
                    await _userManager.ResetAccessFailedCountAsync(user);
                }

                // Create a new authentication ticket.
                var ticket = await CreateTicketAsync(request, user);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            else if (request.IsRefreshTokenGrantType())
            {
                // Retrieve the claims principal stored in the refresh token.
                var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(
                    OpenIddictServerDefaults.AuthenticationScheme);

                // Retrieve the user profile corresponding to the refresh token.
                // Note: if you want to automatically invalidate the refresh token
                // when the user password/roles change, use the following line instead:
                // var user = _signInManager.ValidateSecurityStampAsync(info.Principal);
                var user = await _userManager.GetUserAsync(info.Principal);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The refresh token is no longer valid."
                    }));
                }

                // Ensure the user is still allowed to sign in.
                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The user is no longer allowed to sign in."
                    }));
                }

                // Create a new authentication ticket, but reuse the properties stored
                // in the refresh token, including the scopes originally granted.
                var ticket = await CreateTicketAsync(request, user, info.Properties);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            return(BadRequest(new OpenIdConnectResponse
            {
                Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                ErrorDescription = "The specified grant type is not supported."
            }));
        }
        public async Task <IActionResult> Exchange(OpenIdConnectRequest request)
        {
            Debug.Assert(request.IsTokenRequest(),
                         "The OpenIddict binder for ASP.NET Core MVC is not registered. " +
                         "Make sure services.AddOpenIddict().AddMvcBinders() is correctly called.");

            if (request.IsPasswordGrantType())
            {
                var user = await _userManager.FindByNameAsync(request.Username);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                // Validate the username/password parameters and ensure the account is not locked out.
                var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure : true);

                if (!result.Succeeded)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                // Create a new authentication ticket.
                var ticket = await CreateTicketAsync(request, user);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            else if (request.IsAuthorizationCodeGrantType() || request.IsRefreshTokenGrantType())
            {
                // Retrieve the claims principal stored in the authorization code/refresh token.
                var info = await HttpContext.AuthenticateAsync(OpenIddictServerDefaults.AuthenticationScheme);

                // Retrieve the user profile corresponding to the authorization code/refresh token.
                // Note: if you want to automatically invalidate the authorization code/refresh token
                // when the user password/roles change, use the following line instead:
                // var user = _signInManager.ValidateSecurityStampAsync(info.Principal);
                var user = await _userManager.GetUserAsync(info.Principal);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The token is no longer valid."
                    }));
                }

                // Ensure the user is still allowed to sign in.
                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The user is no longer allowed to sign in."
                    }));
                }

                // Create a new authentication ticket, but reuse the properties stored in the
                // authorization code/refresh token, including the scopes originally granted.
                var ticket = await CreateTicketAsync(request, user, info.Properties);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            return(BadRequest(new OpenIdConnectResponse
            {
                Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                ErrorDescription = "The specified grant type is not supported."
            }));
        }
Пример #5
0
        public async Task <IActionResult> Exchange(OpenIdConnectRequest request)
        {
            if (request.IsPasswordGrantType())
            {
                var user = await _userManager.FindByNameAsync(request.Username);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in."
                    }));
                }

                if (_userManager.SupportsUserTwoFactor && await _userManager.GetTwoFactorEnabledAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The specified user is not allowed to sign in."
                    }));
                }

                if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                if (!await _userManager.CheckPasswordAsync(user, request.Password))
                {
                    if (_userManager.SupportsUserLockout)
                    {
                        await _userManager.AccessFailedAsync(user);
                    }

                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The username/password couple is invalid."
                    }));
                }

                if (_userManager.SupportsUserLockout)
                {
                    await _userManager.ResetAccessFailedCountAsync(user);
                }

                var ticket = await CreateTicketAsync(request, user);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            else if (request.IsRefreshTokenGrantType())
            {
                var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(
                    OpenIdConnectServerDefaults.AuthenticationScheme);

                var user = await _userManager.GetUserAsync(info.Principal);

                if (user == null)
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The refresh token is no longer valid."
                    }));
                }

                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(BadRequest(new OpenIdConnectResponse
                    {
                        Error = OpenIdConnectConstants.Errors.InvalidGrant,
                        ErrorDescription = "The user is no longer allowed to sign in."
                    }));
                }

                var ticket = await CreateTicketAsync(request, user, info.Properties);

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }

            return(BadRequest(new OpenIdConnectResponse
            {
                Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                ErrorDescription = "The specified grant type is not supported."
            }));
        }
Пример #6
0
        public async Task <IActionResult> Exchange()
        {
            var request = HttpContext.GetOpenIddictServerRequest();

            if (request == null)
            {
                throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");
            }

            if (request.IsAuthorizationCodeGrantType() || request.IsRefreshTokenGrantType())
            {
                var principal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)).Principal;

                if (principal == null)
                {
                    throw new InvalidOperationException("The user details cannot be retrieved.");
                }

                var user = await UserService.GetAsync(principal, HttpContext.RequestAborted);

                if (user == null)
                {
                    return(Forbid(
                               new AuthenticationProperties(new Dictionary <string, string?>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
                    }),
                               OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
                }

                if (!await SignInManager.CanSignInAsync((IdentityUser)user.Identity))
                {
                    return(Forbid(
                               new AuthenticationProperties(new Dictionary <string, string?>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
                    }),
                               OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
                }

                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
            }

            if (request.IsClientCredentialsGrantType())
            {
                if (request.ClientId == null)
                {
                    throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");
                }

                var application = await applicationManager.FindByClientIdAsync(request.ClientId, HttpContext.RequestAborted);

                if (application == null)
                {
                    throw new InvalidOperationException("The application details cannot be found in the database.");
                }

                var principal = await CreateApplicationPrincipalAsync(request, application);

                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
            }

            throw new InvalidOperationException("The specified grant type is not supported.");
        }
Пример #7
0
 public async Task <bool> CanSignInAsync(User user)
 {
     return(await _signInManager.CanSignInAsync(user));
 }
Пример #8
0
        public async Task <Result> LoginPhone(LoginPhoneParam model, string returnUrl = null)
        {
            var phone = model.Phone;

            //5分钟内的验证码
            var sms = await _accountService.ValidateGetLastSms(phone, model?.Code);

            //设置验证码被使用
            sms.IsUsed = true;
            await _smsSendRepository.SaveChangesAsync();

            var user = await _userManager.Users.FirstOrDefaultAsync(c => c.PhoneNumber == phone);

            if (user == null)
            {
                return(Result.Fail("用户不存在"));
            }
            if (!user.IsActive)
            {
                return(Result.Fail("用户已禁用"));
            }

            //如果手机没有验证,则自动验证
            if (!user.PhoneNumberConfirmed)
            {
                user.PhoneNumberConfirmed = true;
                await _userManager.UpdateAsync(user);
            }

            var isLockedOut = await _userManager.IsLockedOutAsync(user);

            if (isLockedOut)
            {
                throw new Exception("用户已锁定,请稍后重试");
            }

            if (!await _signInManager.CanSignInAsync(user))
            {
                throw new Exception("用户不允许登录,请稍后重试");
            }

            // 如果手机没有验证,则自动验证
            if (!user.PhoneNumberConfirmed)
            {
                user.PhoneNumberConfirmed = true;
                await _userManager.UpdateAsync(user);
            }

            // 如果用手机登录且双因子=true时,则设置双因子=false
            if (user.TwoFactorEnabled)
            {
                await _userManager.SetTwoFactorEnabledAsync(user, false);
            }

            // 重置错误次数计数器
            var failedCount = await _userManager.GetAccessFailedCountAsync(user);

            if (failedCount > 0)
            {
                await _userManager.ResetAccessFailedCountAsync(user);
            }

            var token = await _tokenService.GenerateAccessToken(user);

            var loginResult = new LoginResult()
            {
                Token  = token,
                Avatar = user.AvatarUrl,
                Email  = user.Email,
                Name   = user.FullName,
                Phone  = user.PhoneNumber
            };

            return(Result.Ok(loginResult));

            //var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
            //if (!userFactors.Any(c => c == nameof(model.Phone)))
            //    return Result.Fail("手机未验证,不允许用手机登录");
            //var isLockedOut = _userManager.IsLockedOutAsync(user);

            //var signInResult = await _shopSignInManager.SignInCheck(user);
            //if (signInResult == null || signInResult.Succeeded)
            //{
            //    //如果返回null,说明被允许登录
            //    //如果用手机登录且双因子=true时,则设置双因子=false
            //    if (user.TwoFactorEnabled)
            //    {
            //        await _userManager.SetTwoFactorEnabledAsync(user, false);
            //    }
            //    var token = await _tokenService.GenerateAccessToken(user);
            //    var loginResult = new LoginResult()
            //    {
            //        Token = token,
            //        Avatar = user.AvatarUrl,
            //        Email = user.Email,
            //        Name = user.FullName,
            //        Phone = user.PhoneNumber
            //    };
            //    return Result.Ok(loginResult);
            //}
            //else if (signInResult.IsLockedOut)
            //{
            //    return Result.Fail("用户已锁定,请稍后重试");
            //}
            //return Result.Fail("用户登录失败,请稍后重试");
        }
Пример #9
0
        public async Task <IActionResult> TokenExchange(OpenIdConnectRequest request)
        {
            // Check to make sure incoming request is an OpenIdConnect password grant request
            if (!request.IsPasswordGrantType())
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
                    ErrorDescription = "The specified grant type is not supported."
                }));
            }

            // Make sure user actually exists in the database
            var user = await _userManager.FindByNameAsync(request.Username);

            if (user == null)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username or password is invalid."
                }));
            }

            // Ensure the user is allowed to sign in
            if (!await _signInManager.CanSignInAsync(user))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The specified user is not allowed to sign in."
                }));
            }

            // Ensure the user is not already locked out
            if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username or password is invalid."
                }));
            }

            // Ensure the password is valid
            if (!await _userManager.CheckPasswordAsync(user, request.Password))
            {
                if (_userManager.SupportsUserLockout)
                {
                    await _userManager.AccessFailedAsync(user);
                }

                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username or password is invalid."
                }));
            }

            // Reset the lockout count
            if (_userManager.SupportsUserLockout)
            {
                await _userManager.ResetAccessFailedCountAsync(user);
            }

            // Look up the user's roles (if any)
            var roles = new string[0];

            if (_userManager.SupportsUserRole)
            {
                roles = (await _userManager.GetRolesAsync(user)).ToArray();
            }

            // Create a new authentication ticket w/ the user identity and their roles (if any)
            var ticket = await CreateTicketAsync(request, user, roles);

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }