Esempio n. 1
0
        public async Task <IActionResult> LoginWith2fa(LoginWith2faViewModel model, bool rememberMe, string returnUrl = "/")
        {
            returnUrl = "/";
            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

            if (user == null)
            {
                throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
            }

            var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);

            var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, model.RememberMachine);

            if (result.Succeeded)
            {
                _logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id);
                return(RedirectToLocal(returnUrl));
            }
            else if (result.IsLockedOut)
            {
                _logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
                return(RedirectToAction(nameof(Lockout)));
            }
            else
            {
                _logger.LogWarning("Invalid authenticator code entered for user with ID {UserId}.", user.Id);
                ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
                return(View());
            }
        }
        public async Task <IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            if (!CanLoginOrRegister())
            {
                return(RedirectToAction("Login"));
            }
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                // Require the user to have a confirmed email before they can log on.
                var user = await _userManager.FindByEmailAsync(model.Email);

                if (user != null)
                {
                    if (user.RequiresEmailConfirmation && !await _userManager.IsEmailConfirmedAsync(user))
                    {
                        ModelState.AddModelError(string.Empty,
                                                 "You must have a confirmed email to log in.");
                        return(View(model));
                    }
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return(View(model));
                }

                var u2fDevices = await _u2FService.HasDevices(user.Id);

                var fido2Devices = await _fido2Service.HasCredentials(user.Id);

                if (!await _userManager.IsLockedOutAsync(user) && u2fDevices || fido2Devices)
                {
                    if (await _userManager.CheckPasswordAsync(user, model.Password))
                    {
                        LoginWith2faViewModel twoFModel = null;

                        if (user.TwoFactorEnabled)
                        {
                            // we need to do an actual sign in attempt so that 2fa can function in next step
                            await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure : true);

                            twoFModel = new LoginWith2faViewModel
                            {
                                RememberMe = model.RememberMe
                            };
                        }

                        return(View("SecondaryLogin", new SecondaryLoginViewModel()
                        {
                            LoginWith2FaViewModel = twoFModel,
                            LoginWithU2FViewModel = u2fDevices? await BuildU2FViewModel(model.RememberMe, user) : null,
                            LoginWithFido2ViewModel = fido2Devices? await BuildFido2ViewModel(model.RememberMe, user): null,
                        }));
                    }
                    else
                    {
                        var incrementAccessFailedResult = await _userManager.AccessFailedAsync(user);

                        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                        return(View(model));
                    }
                }


                var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure : true);

                if (result.Succeeded)
                {
                    _logger.LogInformation($"User '{user.Id}' logged in.");
                    return(RedirectToLocal(returnUrl));
                }
                if (result.RequiresTwoFactor)
                {
                    return(View("SecondaryLogin", new SecondaryLoginViewModel()
                    {
                        LoginWith2FaViewModel = new LoginWith2faViewModel()
                        {
                            RememberMe = model.RememberMe
                        }
                    }));
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning($"User '{user.Id}' account locked out.");
                    return(RedirectToAction(nameof(Lockout)));
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return(View(model));
                }
            }

            // If we got this far, something failed, redisplay form
            return(View(model));
        }
        public async Task <IActionResult> LoginWith2fa(LoginWith2faViewModel model, bool rememberMe, string returnUrl = null)
        {
            ViewData["Title"] = sr["Two-factor authentication"];

            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            //var user = await accountService.GetTwoFactorAuthenticationUserAsync();
            //if (user == null)
            //{
            //    throw new ApplicationException($"Unable to load user with ID '{User.GetUserId()}'.");
            //}

            //var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);

            //var result = await accountService.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, model.RememberMachine);

            //if (result.Succeeded)
            //{
            //    if (!string.IsNullOrEmpty(returnUrl))
            //    {
            //        return LocalRedirect(returnUrl);
            //    }

            //    return this.RedirectToSiteRoot(Site);
            //}

            //if (result.IsLockedOut)
            //{
            //    return HandleLockout();
            //}
            //else
            //{
            //    ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
            //    return View(model);
            //}

            var result = await accountService.Try2FaLogin(model, rememberMe);

            if (result.SignInResult.Succeeded)
            {
                return(await HandleLoginSuccess(result, returnUrl));
            }

            foreach (var reason in result.RejectReasons)
            {
                //these reasons are not meant to be shown in the ui
                // but we can log them so admin will see failed attempts in the log along with reasons
                log.LogWarning(reason);
            }

            if (result.SignInResult.IsNotAllowed)
            {
                return(HandleLoginNotAllowed(result));
            }

            if (result.SignInResult.IsLockedOut)
            {
                return(HandleLockout(result));
            }
            else
            {
                analytics.HandleLoginFail("Onsite", sr["Invalid authenticator code."]).Forget();


                ModelState.AddModelError(string.Empty, sr["Invalid authenticator code."]);
                return(View(model));
            }
        }
Esempio n. 4
0
        public async Task <IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                // Require the user to have a confirmed email before they can log on.
                var user = await _userManager.FindByEmailAsync(model.Email);

                if (user != null)
                {
                    if (user.RequiresEmailConfirmation && !await _userManager.IsEmailConfirmedAsync(user))
                    {
                        ModelState.AddModelError(string.Empty,
                                                 "Debe tener un correo electrónico confirmado para iniciar sesión.");
                        return(View(model));
                    }
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Intento de inicio de sesión no válido.");
                    return(View(model));
                }

                if (!await _userManager.IsLockedOutAsync(user) && await _u2FService.HasDevices(user.Id))
                {
                    if (await _userManager.CheckPasswordAsync(user, model.Password))
                    {
                        LoginWith2faViewModel twoFModel = null;

                        if (user.TwoFactorEnabled)
                        {
                            // we need to do an actual sign in attempt so that 2fa can function in next step
                            await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure : true);

                            twoFModel = new LoginWith2faViewModel
                            {
                                RememberMe = model.RememberMe
                            };
                        }

                        return(View("SecondaryLogin", new SecondaryLoginViewModel()
                        {
                            LoginWith2FaViewModel = twoFModel,
                            LoginWithU2FViewModel = await BuildU2FViewModel(model.RememberMe, user)
                        }));
                    }
                    else
                    {
                        var incrementAccessFailedResult = await _userManager.AccessFailedAsync(user);

                        ModelState.AddModelError(string.Empty, "Intento de inicio de sesión no válido.");
                        return(View(model));
                    }
                }


                var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure : true);

                if (result.Succeeded)
                {
                    _logger.LogInformation("Usuario conectado.");
                    return(RedirectToLocal(returnUrl));
                }
                if (result.RequiresTwoFactor)
                {
                    return(View("SecondaryLogin", new SecondaryLoginViewModel()
                    {
                        LoginWith2FaViewModel = new LoginWith2faViewModel()
                        {
                            RememberMe = model.RememberMe
                        }
                    }));
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("Cuenta de usuario bloqueada.");
                    return(RedirectToAction(nameof(Lockout)));
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Intento de inicio de sesión no válido.");
                    return(View(model));
                }
            }

            // If we got this far, something failed, redisplay form
            return(View(model));
        }
        public async Task <IActionResult> Post([FromBody] LoginWith2faViewModel model)
        {
            var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

            if (user == null)
            {
                return(BadRequest(Errors.AddErrorToModelState("user loading failure", "Unable to load user", ModelState)));
            }

            var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);

            var result = await _signInManager.TwoFactorSignInAsync("Phone", authenticatorCode, false, false);

            if (result.Succeeded)
            {
                var identity = await GetClaimsIdentity(user.UserName);

                var profile = _ctx.UserProfiles.FirstOrDefault(t => t.UserId == user.Id);

                //check if user has refresh token
                var validRefreshToken = _ctx.RefreshTokens.FirstOrDefault(r => r.UserId == user.Id.ToString() && r.IsEnabled);

                if (validRefreshToken != null)
                {
                    if (validRefreshToken.EndDate.AddMinutes(-30) < DateTime.UtcNow)
                    {
                        //create new refresh token
                        RefreshToken rt = new RefreshToken();

                        rt.StartDate = DateTime.UtcNow;

                        DateTime dtmRefreshTokenEndDate = DateTime.UtcNow;
                        dtmRefreshTokenEndDate = dtmRefreshTokenEndDate.AddMonths(6);
                        rt.EndDate             = dtmRefreshTokenEndDate;

                        rt.IsEnabled = true;
                        rt.UserId    = user.Id;

                        bool refreshTokenAdded = false;

                        refreshTokenAdded = await _sqlServerUow.RefreshTokens.AddAsync(rt);

                        // Serialize and return the response
                        var response = new
                        {
                            id                      = user.Id,
                            auth_token              = await _jwtFactory.GenerateEncodedToken(user.UserName, identity),
                            auth_token_valid        = (int)_jwtOptions.ValidFor.TotalSeconds,
                            auth_token_created      = _jwtOptions.IssuedAt,
                            auth_token_expires      = _jwtOptions.Expiration,
                            refresh_token           = rt.RefreshTokenId,
                            two_factor_auth_enabled = true,
                            phone_number            = user.PhoneNumber,
                            email                   = user.Email,
                            first_name              = profile.FirstName,
                            surname                 = profile.Surname
                        };

                        var json = JsonConvert.SerializeObject(response, _serializerSettings);
                        return(new OkObjectResult(json));
                    }
                    else
                    {
                        // Serialize and return the response
                        var response = new
                        {
                            id                      = user.Id,
                            auth_token              = await _jwtFactory.GenerateEncodedToken(user.UserName, identity),
                            auth_token_valid        = (int)_jwtOptions.ValidFor.TotalSeconds,
                            auth_token_created      = _jwtOptions.IssuedAt,
                            auth_token_expires      = _jwtOptions.Expiration,
                            refresh_token           = validRefreshToken.RefreshTokenId,
                            two_factor_auth_enabled = true,
                            phone_number            = user.PhoneNumber,
                            email                   = user.Email,
                            first_name              = profile.FirstName,
                            surname                 = profile.Surname
                        };

                        var json = JsonConvert.SerializeObject(response, _serializerSettings);
                        return(new OkObjectResult(json));
                    }
                }
                else
                {
                    //create refresh token
                    RefreshToken rt = new RefreshToken();

                    rt.StartDate = DateTime.UtcNow;

                    DateTime dtmRefreshTokenEndDate = DateTime.UtcNow;
                    dtmRefreshTokenEndDate = dtmRefreshTokenEndDate.AddMonths(6);
                    rt.EndDate             = dtmRefreshTokenEndDate;

                    rt.IsEnabled = true;
                    rt.UserId    = identity.Claims.Single(c => c.Type == "id").Value;

                    bool refreshTokenAdded = false;

                    refreshTokenAdded = await _sqlServerUow.RefreshTokens.AddAsync(rt);

                    // Serialize and return the response
                    var response = new
                    {
                        id                      = user.Id,
                        auth_token              = await _jwtFactory.GenerateEncodedToken(user.UserName, identity),
                        auth_token_valid        = (int)_jwtOptions.ValidFor.TotalSeconds,
                        auth_token_created      = _jwtOptions.IssuedAt,
                        auth_token_expires      = _jwtOptions.Expiration,
                        refresh_token           = rt.RefreshTokenId,
                        two_factor_auth_enabled = true,
                        phone_number            = user.PhoneNumber,
                        email                   = user.Email,
                        first_name              = profile.FirstName,
                        surname                 = profile.Surname
                    };

                    var json = JsonConvert.SerializeObject(response, _serializerSettings);
                    return(new OkObjectResult(json));
                }
            }
            else if (result.IsLockedOut)
            {
                return(BadRequest(Errors.AddErrorToModelState("login_failure", "Locked out.", ModelState)));
            }
            else
            {
                return(BadRequest(Errors.AddErrorToModelState("login_failure", "Invalid authenticator code.", ModelState)));
            }
        }