Esempio n. 1
0
        public async Task <ActionResult <UserDetail> > PostLogin(LoginModel loginModel)
        {
            // Sign the user in with username/password, this also gives a chance for developers to
            // custom verify the credentials and auto-link user accounts with a custom IBackOfficePasswordChecker
            SignInResult result = await _signInManager.PasswordSignInAsync(
                loginModel.Username, loginModel.Password, isPersistent : true, lockoutOnFailure : true);

            if (result.Succeeded)
            {
                // return the user detail
                return(GetUserDetail(_userService.GetByUsername(loginModel.Username)));
            }

            if (result.RequiresTwoFactor)
            {
                var twofactorView = _backOfficeTwoFactorOptions.GetTwoFactorView(loginModel.Username);
                if (twofactorView.IsNullOrWhiteSpace())
                {
                    return(new ValidationErrorResult($"The registered {typeof(IBackOfficeTwoFactorOptions)} of type {_backOfficeTwoFactorOptions.GetType()} did not return a view for two factor auth "));
                }

                IUser attemptedUser = _userService.GetByUsername(loginModel.Username);

                // create a with information to display a custom two factor send code view
                var verifyResponse = new ObjectResult(new
                {
                    twoFactorView = twofactorView,
                    userId        = attemptedUser.Id
                })
                {
                    StatusCode = StatusCodes.Status402PaymentRequired
                };

                return(verifyResponse);
            }

            // TODO: We can check for these and respond differently if we think it's important
            //  result.IsLockedOut
            //  result.IsNotAllowed

            // return BadRequest (400), we don't want to return a 401 because that get's intercepted
            // by our angular helper because it thinks that we need to re-perform the request once we are
            // authorized and we don't want to return a 403 because angular will show a warning message indicating
            // that the user doesn't have access to perform this function, we just want to return a normal invalid message.
            return(BadRequest());
        }
Esempio n. 2
0
        private async Task <IActionResult> ExternalSignInAsync(ExternalLoginInfo loginInfo, Func <IActionResult> response)
        {
            if (loginInfo == null)
            {
                throw new ArgumentNullException(nameof(loginInfo));
            }
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            // Sign in the user with this external login provider (which auto links, etc...)
            SignInResult result = await _signInManager.ExternalLoginSignInAsync(loginInfo, isPersistent : false);

            var errors = new List <string>();

            if (result == SignInResult.Success)
            {
                // Update any authentication tokens if succeeded
                await _signInManager.UpdateExternalAuthenticationTokensAsync(loginInfo);

                // Check if we are in an upgrade state, if so we need to redirect
                if (_runtimeState.Level == Core.RuntimeLevel.Upgrade)
                {
                    // redirect to the the installer
                    return(Redirect("/"));
                }
            }
            else if (result == SignInResult.TwoFactorRequired)
            {
                var attemptedUser = await _userManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey);

                if (attemptedUser == null)
                {
                    return(new ValidationErrorResult($"No local user found for the login provider {loginInfo.LoginProvider} - {loginInfo.ProviderKey}"));
                }

                var twofactorView = _backOfficeTwoFactorOptions.GetTwoFactorView(attemptedUser.UserName);
                if (twofactorView.IsNullOrWhiteSpace())
                {
                    return(new ValidationErrorResult($"The registered {typeof(IBackOfficeTwoFactorOptions)} of type {_backOfficeTwoFactorOptions.GetType()} did not return a view for two factor auth "));
                }

                // create a with information to display a custom two factor send code view
                var verifyResponse = new ObjectResult(new
                {
                    twoFactorView = twofactorView,
                    userId        = attemptedUser.Id
                })
                {
                    StatusCode = StatusCodes.Status402PaymentRequired
                };

                return(verifyResponse);
            }
            else if (result == SignInResult.LockedOut)
            {
                errors.Add($"The local user {loginInfo.Principal.Identity.Name} for the external provider {loginInfo.ProviderDisplayName} is locked out.");
            }
            else if (result == SignInResult.NotAllowed)
            {
                // This occurs when SignInManager.CanSignInAsync fails which is when RequireConfirmedEmail , RequireConfirmedPhoneNumber or RequireConfirmedAccount fails
                // however since we don't enforce those rules (yet) this shouldn't happen.
                errors.Add($"The user {loginInfo.Principal.Identity.Name} for the external provider {loginInfo.ProviderDisplayName} has not confirmed their details and cannot sign in.");
            }
            else if (result == SignInResult.Failed)
            {
                // Failed only occurs when the user does not exist
                errors.Add("The requested provider (" + loginInfo.LoginProvider + ") has not been linked to an account, the provider must be linked from the back office.");
            }
            else if (result == AutoLinkSignInResult.FailedNotLinked)
            {
                errors.Add("The requested provider (" + loginInfo.LoginProvider + ") has not been linked to an account, the provider must be linked from the back office.");
            }
            else if (result == AutoLinkSignInResult.FailedNoEmail)
            {
                errors.Add($"The requested provider ({loginInfo.LoginProvider}) has not provided the email claim {ClaimTypes.Email}, the account cannot be linked.");
            }
            else if (result is AutoLinkSignInResult autoLinkSignInResult && autoLinkSignInResult.Errors.Count > 0)
            {
                errors.AddRange(autoLinkSignInResult.Errors);
            }