public async Task <IActionResult> OnPostAsync(string returnUrl = null) { returnUrl = returnUrl ?? Url.Content("~/"); if (ModelState.IsValid) { var(logonResult, signInResult) = await DoLogon(returnUrl); if (!signInResult.Succeeded) { return(logonResult); } var ids = (await _keyStore.GetCredentialIdsForUser(Input.Email))?.ToList(); if (ids == null || ids.Count == 0) { return(logonResult); } else { await _signInManager.SignOutAsync(); await HttpContext.SignInAsync(IdentityConstants.TwoFactorUserIdScheme, new ClaimsPrincipal(new ClaimsIdentity( BuildClaims(Input.Email, Input.Password, Input.RememberMe), IdentityConstants.TwoFactorUserIdScheme))); return(Redirect("/Fido/Login")); } } // If we got this far, something failed, redisplay form return(Page()); }
public async Task <IActionResult> OnPostAsync() { var user = await _userManager.GetUserAsync(User); if (user == null) { return(NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.")); } var credentialIds = (await _store.GetCredentialIdsForUser(user.Email)).ToList(); if (credentialIds.Any()) { foreach (var credId in credentialIds) { var cred = await _store.GetCredentialById(credId); // TODO: Add FIDO credential removal logic //await _store.Remove(cred); (_store as InMemoryFidoKeyStore).Keys.Remove(cred); // Workaround... } } var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); if (!disable2faResult.Succeeded) { throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{_userManager.GetUserId(User)}'."); } _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; return(RedirectToPage("./TwoFactorAuthentication")); }
public async Task <IActionResult> OnGet() { var user = await _userManager.GetUserAsync(User); if (user == null) { return(NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.")); } HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null; Is2faEnabled = await _userManager.GetTwoFactorEnabledAsync(user); IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user); RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user); SecurityKeys = new List <RegisteredSecurityKeyModel>(); var credentialIds = (await _store.GetCredentialIdsForUser(user.Email)).ToList(); HasSecurityKey = credentialIds.Any(); if (HasSecurityKey) { var id = 0; foreach (var credId in credentialIds) { id += 1; var cred = await _store.GetCredentialById(credId); SecurityKeys.Add(new RegisteredSecurityKeyModel { Id = WebEncoders.Base64UrlEncode(cred.CredentialId), DeviceName = cred.DisplayFriendlyName }); } } return(Page()); }
public async Task <IActionResult> OnPostAsync(string returnUrl = null) { returnUrl = returnUrl ?? Url.Content("~/"); _logger.LogInformation("log"); if (ModelState.IsValid) { // This doesn't count login failures towards account lockout // To enable password failures to trigger account lockout, set lockoutOnFailure: true var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure : true); if (result.Succeeded) { _logger.LogInformation("User logged in."); return(LocalRedirect(returnUrl)); } if (result.RequiresTwoFactor) { var credentialIds = (await _store.GetCredentialIdsForUser(Input.Email)).ToList(); if (credentialIds.Any()) { return(RedirectToPage("./LoginWithSecurityKey", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe })); } return(RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe })); } if (result.IsLockedOut) { _logger.LogWarning("User account locked out."); return(RedirectToPage("./Lockout")); } else { ModelState.AddModelError(string.Empty, "Invalid login attempt."); return(Page()); } } // If we got this far, something failed, redisplay form return(Page()); }
public async Task <IActionResult> Login(LoginModel model) { if (ModelState.IsValid) { IdentityUser user = await signInManager.UserManager.FindByNameAsync(model.Username); if (user != null) { // password auth SignInResult result = await signInManager.CheckPasswordSignInAsync(user, model.Password, true); if (result.Succeeded) { // TODO: FIDO2 var keys = await fidoStore.GetCredentialIdsForUser(model.Username); if (keys.Any()) { await HttpContext.SignInAsync(IdentityConstants.TwoFactorUserIdScheme, new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("userId", model.Username) }, IdentityConstants.TwoFactorUserIdScheme))); return(RedirectToAction("FidoLogin")); } // start session (with ASP.NET Identity cookie) var userPrincipal = await signInManager.CreateUserPrincipalAsync(user); await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, userPrincipal, new AuthenticationProperties()); if (model.ReturnUrl != null && Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } return(Redirect("/")); } } } ModelState.AddModelError("", "Invalid username/password"); return(View(model)); }
public async Task <IActionResult> Login(LoginInputModel model, string button) { // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); // the user clicked the "cancel" button if (button != "login") { if (context != null) { // if the user cancels, send a result back into IdentityServer as if they // denied the consent (even if this client does not require consent). // this will send back an access denied OIDC error response to the client. await _interaction.GrantConsentAsync(context, ConsentResponse.Denied); // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null if (await _clientStore.IsPkceClientAsync(context.ClientId)) { // if the client is PKCE then we assume it's native, so this change in how to // return the response is for better UX for the end user. return(View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl })); } return(Redirect(model.ReturnUrl)); } else { // since we don't have a valid context, then we just go back to the home page return(Redirect("~/")); } } if (ModelState.IsValid) { // validate username/password against in-memory store if (_users.ValidateCredentials(model.Username, model.Password)) { var ids = (await _keystore.GetCredentialIdsForUser(model.Username))?.ToList(); if (ids == null || ids.Count == 0) { return(await DoLogin(model, context)); } else { await HttpContext.SignInAsync(IdentityConstants.TwoFactorUserIdScheme, new ClaimsPrincipal(new ClaimsIdentity( BuildClaims(model), IdentityConstants.TwoFactorUserIdScheme))); return(Redirect("/Account/FidoLogin")); } } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId : context?.ClientId)); ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }