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.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null if (context.IsNativeClient()) { // The client is native, so this change in how to // return the response is for better UX for the end user. return(this.LoadingPage("Redirect", 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 (await _localUserService.ValidateCredentialsAsync( model.Username, model.Password)) { var user = await _localUserService.GetUserByUserNameAsync(model.Username); // issue temporary authentication ticket var temporaryIdentity = new ClaimsIdentity(); temporaryIdentity.AddClaim(new Claim(JwtClaimTypes.Subject, user.Subject)); await HttpContext.SignInAsync("idsrv.mfa", new ClaimsPrincipal(temporaryIdentity)); // if there's no TOTP secret registered for this user, send an OTP via // mail as backup if (!(await _localUserService.UserHasRegisteredTotpSecret(user.Subject))) { return(RedirectToAction( "RegisterForMfa", "MfaRegistration", new { returnUrl = Request.Path + Request.QueryString, })); } var redirectToAdditionalFactorUrl = Url.Action("AdditionalAuthenticationFactor", new { returnUrl = model.ReturnUrl, rememberLogin = model.RememberLogin }); return(Redirect(redirectToAdditionalFactorUrl)); } await _events.RaiseAsync( new UserLoginFailureEvent( model.Username, "invalid credentials", clientId : context?.Client.ClientId)); ModelState.AddModelError( string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }