public override async ValueTask HandleAsync( OpenIddictServerEvents.HandleTokenRequestContext notification) { var request = notification.Request; if (!request.IsPasswordGrantType()) { return; } var httpContext = notification.Transaction.GetHttpRequest().HttpContext; await _rateLimitService.Throttle(ZoneLimits.Login, httpContext.Connection.RemoteIpAddress.ToString(), httpContext.RequestAborted); var user = await _userManager.FindByNameAsync(request.Username); if (user == null || await _u2FService.HasDevices(user.Id) || !(await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure: true)) .Succeeded) { notification.Reject( error: OpenIddictConstants.Errors.InvalidGrant, description: "The specified credentials are invalid."); return; } notification.Principal = await CreateClaimsPrincipalAsync(request, user); notification.HandleAuthentication(); }
public override async Task <OpenIddictServerEventState> HandleAsync( OpenIddictServerEvents.HandleTokenRequest notification) { var request = notification.Context.Request; if (!request.IsPasswordGrantType()) { // Allow other handlers to process the event. return(OpenIddictServerEventState.Unhandled); } // Validate the user credentials. // Note: to mitigate brute force attacks, you SHOULD strongly consider // applying a key derivation function like PBKDF2 to slow down // the password validation process. You SHOULD also consider // using a time-constant comparer to prevent timing attacks. var user = await _userManager.FindByNameAsync(request.Username); if (user == null || await _u2FService.HasDevices(user.Id) || !(await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure: true)) .Succeeded) { notification.Context.Reject( error: OpenIddictConstants.Errors.InvalidGrant, description: "The specified credentials are invalid."); // Don't allow other handlers to process the event. return(OpenIddictServerEventState.Handled); } notification.Context.Validate(await CreateTicketAsync(request, user)); // Don't allow other handlers to process the event. return(OpenIddictServerEventState.Handled); }
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> 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)); }