public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = AutoProvisionUser(provider, providerUserId, claims); } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username)); // issue authentication cookie for user var isuser = new IdentityServerUser(user.SubjectId) { DisplayName = user.Username, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); if (context != null) { if (await _clientStore.IsPkceClientAsync(context.Client.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 = returnUrl })); } } return(Redirect(returnUrl)); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } var tokens = result.Properties.GetTokens(); var accessToken = tokens.Where(t => t.Name == "access_token").FirstOrDefault(); // lookup our user and external provider info var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user //user = AutoProvisionUser(provider, providerUserId, claims); return(RedirectToAction("Connect")); } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); if (provider == "Microsoft" && accessToken != null) { HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken.Value}"); var info = await client.GetAsync($"https://graph.microsoft.com/v1.0/users/{providerUserId}?$select=businessPhones,displayName,givenName,id,jobTitle,mail,mobilePhone,preferredLanguage,surname,userPrincipalName,department"); var content = await info.Content.ReadAsAsync <dynamic>(); if (content != null) { try { string jobTitle = content.jobTitle; additionalLocalClaims.Add(new Claim("jobTitle", jobTitle)); if (jobTitle == "uèitel") { await _userManager.AddToRoleAsync(user, Constants.TeacherRole); } else { await _userManager.RemoveFromRoleAsync(user, Constants.TeacherRole); } if (jobTitle == "student") { await _userManager.AddToRoleAsync(user, Constants.StudentRole); } else { await _userManager.RemoveFromRoleAsync(user, Constants.StudentRole); } if (jobTitle == "vedení školy") { await _userManager.AddToRoleAsync(user, Constants.ManagerRole); await _userManager.AddToRoleAsync(user, Constants.TeacherRole); } else { await _userManager.RemoveFromRoleAsync(user, Constants.ManagerRole); } } catch { } try { var oldClaims = await _userManager.GetClaimsAsync(user); var oldDepartmentClaim = oldClaims.Where(c => c.Type == "department").SingleOrDefault(); ; if (oldDepartmentClaim != null) { await _userManager.RemoveClaimAsync(user, oldDepartmentClaim); } string department = content.department; await _userManager.AddClaimAsync(user, new Claim("department", department)); additionalLocalClaims.Add(new Claim("department", department)); } catch { } } } foreach (var claim in claims) { additionalLocalClaims.Add(claim); } var roles = await _userManager.GetRolesAsync(user); foreach (var role in roles) { additionalLocalClaims.Add(new Claim("role", role)); var r = await _roleManager.FindByNameAsync(role); var claimsInRole = await _roleManager.GetClaimsAsync(r); foreach (var cl in claimsInRole) { additionalLocalClaims.Add(new Claim(cl.Type, cl.Value)); } } IList <Claim> userClaims = await _userManager.GetClaimsAsync(user); foreach (var uc in userClaims) { additionalLocalClaims.Add(new Claim(uc.Type, uc.Value)); } // issue authentication cookie for user await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, user.UserName)); var isuser = new IdentityServerUser(user.Id) { DisplayName = user.UserName, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); if (context != 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", returnUrl)); } } return(Redirect(returnUrl)); }
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(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 (_users.ValidateCredentials(model.Username, model.Password)) { var user = _users.FindByUsername(model.Username); await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId : context?.ClientId)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(user.SubjectId) { DisplayName = user.Username }; await HttpContext.SignInAsync(isuser, props); if (context != 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(this.LoadingPage("Redirect", model.ReturnUrl)); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(model.ReturnUrl)); } // request for a local page if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } else { // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } } 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)); }
public async Task <IActionResult> Login([FromBody] SessionCreateForm form) { // El form está comlpeto? -------------------- if (form == null) { return(new BadRequestResult()); } if (string.IsNullOrEmpty(form.UsernameOrEmail)) { ModelState.AddModelError(nameof(form.UsernameOrEmail), "Required"); } if (string.IsNullOrEmpty(form.Password)) { ModelState.AddModelError(nameof(form.Password), "Required"); } if (!ModelState.IsValid) { return(ValidationError()); } // La IP tiene permiso de intentar login? -------------------- var attemptRateResult = await LoginAttemptLimitingService.Check(RequestInfoService.RemoteIp, LoginAttemptStore); if (!attemptRateResult.IsApproved) { ModelState.AddModelError("", attemptRateResult.ErrorMessage); return(ValidationError()); } LoginAttempt attempt = new LoginAttempt(this.RequestInfoService.RemoteIp, DateTime.UtcNow); // La credencial existe? -------------------- string failedLoginMsg = "Invalid email and password combination."; Credential credential = null; bool isEmail = form.UsernameOrEmail.IsEmail(); if (isEmail) { credential = await CredentialStore.GetByEmail(form.UsernameOrEmail); } else { credential = await CredentialStore.Get(form.UsernameOrEmail); } if (credential == null) { ModelState.AddModelError("", failedLoginMsg); await LoginAttemptStore.Create(attempt); return(ValidationError()); } // La contraseña es correcta? string newCalculatedHash = HashingUtil.GenerateHash(form.Password, credential.PasswordSalt); if (newCalculatedHash != credential.PasswordHash) { ModelState.AddModelError("", failedLoginMsg); await LoginAttemptStore.Create(attempt); return(ValidationError()); } // El usuario está penalizado? CredentialPenalty activePenalty = await CredentialPenaltyStore.Get(credential.CredentialId, DateTime.UtcNow); if (activePenalty != null) { string validationMsg = null; if (activePenalty.EndDate.HasValue) { validationMsg = string.Format("User temporarily banned, until [{0}]. Reason: '{1}'", activePenalty.EndDate.Value.ToString(), activePenalty.Reason); } else { validationMsg = string.Format("User permanently banned. Reason: '{0}'", activePenalty.Reason); } ModelState.AddModelError("", validationMsg); await LoginAttemptStore.Create(attempt); return(ValidationError()); } var agent = RequestInfoService.UserAgent; // La credencial ya tiene una sesión activa? Session session = await this.SessionStore.Get( credential.CredentialId, agent.DeviceClass, agent.DeviceName, agent.AgentName, agent.AgentVersion); if (session != null) { session.LastActiveDate = DateTime.UtcNow; if (session.AllowSelfRenewal) { session.ExpirationDate = session.LastActiveDate.AddDays(1); } await SessionStore.Update(session); } else { // Crea la sesión session = new Session(); session.CredentialId = credential.CredentialId; session.LoginDate = DateTime.UtcNow; session.ExpirationDate = DateTime.UtcNow.AddDays(1); session.LastActiveDate = session.LoginDate; session.AllowSelfRenewal = form.IsRememberLogin; session.Device = new UserDevice(agent.DeviceClass, agent.DeviceName); session.Agent = new UserAgent(agent.AgentName, agent.AgentVersion); await SessionStore.Create(session); } // Autentifica // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(form.ReturnUrl); await _events.RaiseAsync(new UserLoginSuccessEvent(credential.DisplayName, credential.CredentialId, credential.DisplayName, clientId : context?.ClientId)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (form.IsRememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromHours(8)) }; } ; // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(credential.CredentialId) { DisplayName = credential.DisplayName }; await HttpContext.SignInAsync(isuser, props); // Devuelve el recurso Session return(Element <Session>(session)); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } var externalUser = result.Principal; string FullName = externalUser.FindFirst(ClaimTypes.Name)?.Value ?? " "; string GivenName = externalUser.FindFirst(ClaimTypes.GivenName)?.Value ?? " "; string Surname = externalUser.FindFirst(ClaimTypes.Surname)?.Value ?? " "; string Email = externalUser.FindFirst(ClaimTypes.Email)?.Value; // lookup our user and external provider info var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); if (user == null) { var newUser = new User { Name = GivenName, Username = Email, Password = "", Profile = "Everyone", Email = Email, Provider = provider, UserProviderId = providerUserId }; _userRepository.Add(newUser); user = newUser; } else { user.UserProviderId = providerUserId; user.Provider = provider; _userRepository.Update(user); _userRepository.Save(); } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.UsersId.ToString(), user.Username)); var isuser = new IdentityServerUser(user.UsersId.ToString()) { DisplayName = user.Username, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); if (context != null) { if (await _clientStore.IsPkceClientAsync(context.Client.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 = returnUrl })); } } return(Redirect(returnUrl)); }
public async Task <IActionResult> Login(LoginInputModel model, string button) { var context = await _interactionService.GetAuthorizationContextAsync(model.ReturnUrl); if (button != "login") { if (context == null) { return(Redirect("~/")); } await _interactionService.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); return(context.IsNativeClient() ? this.LoadingPage("Redirect", model.ReturnUrl) : Redirect(model.ReturnUrl)); } if (ModelState.IsValid) { var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, true); if (result.Succeeded) { var user = await _userManager.FindByNameAsync(model.Username); await _eventService.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId : context?.Client.ClientId)); AuthenticationProperties properties = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { properties = new AuthenticationProperties { ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration), IsPersistent = true }; } var issuer = new IdentityServerUser(user.Id) { DisplayName = user.UserName }; await HttpContext.SignInAsync(issuer, properties); if (context != null) { return(context.IsNativeClient() ? this.LoadingPage("Redirect", model.ReturnUrl) : Redirect(model.ReturnUrl)); } if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } throw new Exception("InvalidReturnUrl"); } await _eventService.RaiseAsync(new UserLoginFailureEvent(model.Username, "InvalidCredentials", clientId : context?.Client.ClientId)); ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }
public async Task <IActionResult> ExternalLoginCallback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = await AutoProvisionUserAsync(provider, providerUserId, claims); } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user // we must issue the cookie maually, and can't use the SignInManager because // it doesn't expose an API to issue additional claims from the login workflow var principal = await _signInManager.CreateUserPrincipalAsync(user); additionalLocalClaims.AddRange(principal.Claims); var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id.ToString(); await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), name)); //await HttpContext.SignInAsync(user.Id.ToString(), name, provider, localSignInProps, additionalLocalClaims.ToArray()); var isuser = new IdentityServerUser(user.Id.ToString()) { DisplayName = name, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); // validate return URL and redirect back to authorization endpoint or a local page var returnUrl = result.Properties.Items["returnUrl"]; if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl)) { return(Redirect(returnUrl)); } return(Redirect("~/")); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); _logger.LogDebug("External claims: {@claims}", externalClaims); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = await FindUserFromExternalProvider(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = await AutoProvisionUser(provider, providerUserId, claims); } // this allows us to collect any additional claims or properties // for the specific protocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); var principal = await _signInManager.CreateUserPrincipalAsync(user); additionalLocalClaims.AddRange(principal.Claims); var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id; await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name)); var isuser = new IdentityServerUser(user.Id) { DisplayName = user.UserName }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); // validate return URL and redirect back to authorization endpoint or a local page var returnUrl = result.Properties.Items["returnUrl"]; if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl)) { return(Redirect(returnUrl)); } return(Redirect("~/")); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); _logger.LogDebug("External claims: {@claims}", externalClaims); } var info = await _signInManager.GetExternalLoginInfoAsync(); // lookup our user and external provider info var(user, authProvider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result); if (user == null) { // TODO: Enable support for custom workflows user = await AutoProvisionUserAsync(authProvider, providerUserId, result); } else { await authProvider.UpdateUserAsync(user, result); } var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); //ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); //ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user // we must issue the cookie maually, and can't use the SignInManager because // it doesn't expose an API to issue additional claims from the login workflow var principal = await _signInManager.CreateUserPrincipalAsync(user); additionalLocalClaims.AddRange(principal.Claims); var isuser = new IdentityServerUser(user.Id.ToString()) { IdentityProvider = authProvider.Scheme, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); await _userManager.UpdateAsync(user); await _events.RaiseAsync(new UserLoginSuccessEvent(authProvider.Scheme, providerUserId, user.Id.ToString(), user.Email, true, context?.ClientId)); if (context != null) { var client = await _clientStore.FindClientByIdAsync(context.ClientId); if (client.RequirePkce) { // 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 = returnUrl })); } } return(Redirect(returnUrl)); }
public async Task <IResponseOutput> Login(LoginInput input) { if (!ModelState.IsValid) { return(ResponseOutput.NotOk(ModelState.Values.First().Errors[0].ErrorMessage)); } var sw = new Stopwatch(); sw.Start(); var context = await _interaction.GetAuthorizationContextAsync(input.ReturnUrl); var user = await _userRepository.Select.Where(a => a.UserName == input.UserName) .ToOneAsync(a => new { a.Id, a.Password, a.NickName }); if (user == null) { return(ResponseOutput.NotOk("", 1)); } var password = MD5Encrypt.Encrypt32(input.Password); if (user.Password != password) { return(ResponseOutput.NotOk("", 2)); } AuthenticationProperties props = null; if (input.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1)) }; } ; var identityServerUser = new IdentityServerUser(user.Id.ToString()) { DisplayName = input.UserName }; await HttpContext.SignInAsync(identityServerUser, props); sw.Stop(); //写登录日志 var loginLogEntity = new LoginLogEntity() { CreatedUserId = user.Id, NickName = user.NickName, CreatedUserName = input.UserName, ElapsedMilliseconds = sw.ElapsedMilliseconds, Status = true }; await AddLoginLog(loginLogEntity); return(ResponseOutput.Ok()); }
public async Task <IActionResult> Login(LoginInputModel model) { // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); if (ModelState.IsValid) { AuthenticationProperties props = null; IdentityServerUser isuser = null; UserLoginSuccessEvent successEvent = null; bool isValid = false; string errMsg = null; // 测试用户 var testUser = OAuthConfig.GetTestUsers().Find(t => t.Username == model.Username && t.Password == model.Password); if (testUser != null) { successEvent = new UserLoginSuccessEvent(testUser.Username, testUser.SubjectId, testUser.Username, clientId: context?.Client.ClientId); // issue authentication cookie with subject ID and username isuser = new IdentityServerUser(testUser.SubjectId) { DisplayName = testUser.Username, AdditionalClaims = { new Claim(UserClaimEnum.UserId.ToString(), testUser.SubjectId), new Claim(UserClaimEnum.UserName.ToString(), testUser.Username) } }; isValid = true; } else { //E登账号 var edUser = _edApiService.GetEdUser(model.Username, model.Password, out string msg); errMsg = msg; if (edUser != null) { successEvent = new UserLoginSuccessEvent(edUser.LoginName, edUser.ID.ToString(), edUser.EmployeeName, clientId: context?.Client.ClientId); // issue authentication cookie with subject ID and username isuser = new IdentityServerUser(edUser.ID.ToString()) { DisplayName = edUser.EmployeeName, AdditionalClaims = { new Claim(UserClaimEnum.UserId.ToString(), edUser.ID.ToString()), new Claim(UserClaimEnum.UserName.ToString(), edUser.EmployeeName.ToString()) } }; isValid = true; } } if (isValid) { //身份认证通过 await _events.RaiseAsync(successEvent); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; await HttpContext.SignInAsync(isuser, props); if (context != 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)); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(model.ReturnUrl)); } // request for a local page if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } else { // user might have clicked on a malicious link - should be logged throw new Exception("无效的返回URL"); } } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "无效的证书", clientId : context?.Client.ClientId)); ModelState.AddModelError(string.Empty, errMsg ?? AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { _logger.Exception(result.Failure); string errMsg = "External authentication error - " + result.Failure.Message; errMsg += (result.Failure.InnerException != null) ? (" - " + result.Failure.InnerException.Message) : string.Empty; throw new HttpRequestException( CDCavell.ClassLibrary.Web.Html.StatusCodes.ToString(401), new Exception(errMsg), HttpStatusCode.Unauthorized ); } if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); _logger.Debug($"External claims: {externalClaims}"); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = await AutoProvisionUserAsync(provider, providerUserId, claims); } // validate email address if (!user.EmailConfirmed) { // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); TempData["Email"] = user.Email; return(RedirectToAction("Index", "Registration")); } if (user.TwoFactorEnabled) { TwoFactorValidateModel model = new TwoFactorValidateModel(); model.Email = user.Email; model.Provider = provider; model.ProviderUserId = providerUserId; model.ReturnUrl = result.Properties.Items["returnUrl"]; // if the external system sent a session id claim, copy it over // so we can use it for single sign-out var sid = result.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); if (sid != null) { model.SessionId = sid.Value; } // if the external provider issued an id_token, we'll keep it for signout var idToken = result.Properties.GetTokenValue("id_token"); if (idToken != null) { model.AuthenticationToken = idToken; } TempData["TwoFactorValidateModel"] = JsonConvert.SerializeObject(model); return(RedirectToAction("Validate", "TwoFactor")); } // this allows us to collect any additional claims or properties // for the specific protocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user // we must issue the cookie maually, and can't use the SignInManager because // it doesn't expose an API to issue additional claims from the login workflow var principal = await _signInManager.CreateUserPrincipalAsync(user); additionalLocalClaims.AddRange(principal.Claims); var name = user.FullName; //principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id; var isuser = new IdentityServerUser(user.Id) { DisplayName = name, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name, true, context?.Client.ClientId)); if (context != 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", returnUrl)); } } return(Redirect(returnUrl)); }
public async Task <IActionResult> Callback(string code, string state, string session_state) { // Get the return url for the frontend from the cookies. string returnUrl = HttpContext.Request.Cookies["returnUrl"]; HttpContext.Response.Cookies.Delete("returnUrl"); //Request an accesstoken and idtoken from the authority. RestClient client = new RestClient(config.FfhictOIDC.Authority + "/connect/token"); RestRequest request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.AddParameter("grant_type", "authorization_code"); request.AddParameter("code", code); request.AddParameter("redirect_uri", config.FfhictOIDC.RedirectUri); request.AddParameter("client_id", config.FfhictOIDC.ClientId); request.AddParameter("client_secret", config.FfhictOIDC.ClientSecret); IRestResponse response = client.Execute(request); if (response.StatusCode != HttpStatusCode.OK) { return(BadRequest("Could not validate the identity server authentication.")); } // Parse the content to get the access token. ExternalConnectToken fhictToken = JsonConvert.DeserializeObject <ExternalConnectToken>(response.Content); if (string.IsNullOrWhiteSpace(fhictToken.AccessToken)) { throw new Exception("The FHICT didn't return a correct response. Is the FHICT server accessible?", new Exception( "Content:\n" + response.Content + "\n\nError:\n" + response.ErrorMessage, response.ErrorException)); } JwtSecurityToken jwt = new JwtSecurityToken(fhictToken.AccessToken); string idp = (string)jwt.Payload.FirstOrDefault(c => c.Key.Equals("idp")) .Value; string iss = (string)jwt.Payload.FirstOrDefault(c => c.Key.Equals("iss")) .Value; ExternalResult result = new ExternalResult { Schema = iss, Claims = jwt.Claims, ReturnUrl = returnUrl, IdToken = fhictToken.IdToken }; // lookup our user and external provider info (IdentityUser user, string provider, string providerUserId, IEnumerable <Claim> claims) = await FindUserFromExternalProvider(result); if (user == null) { //Retrieve more user information from the external source. // Get User information RestClient informationClient = new RestClient($"{iss}/connect/userinfo"); RestRequest informationRequest = new RestRequest(Method.GET); informationRequest.AddHeader("Authorization", $"Bearer {fhictToken.AccessToken}"); IRestResponse informationResponse = informationClient.Execute(informationRequest); ExternalUserInfo userinfo = JsonConvert.DeserializeObject <ExternalUserInfo>(informationResponse.Content); List <Claim> claimsList = claims.ToList(); claimsList.Add(new Claim("email", userinfo.PreferredUsername)); claimsList.Add(new Claim("idp", idp)); claimsList.Add(new Claim("name", userinfo.Name)); IdentityUser toInsertuser = new IdentityUser { ProviderId = provider, ExternalSubjectId = providerUserId, Email = userinfo.Email, Firstname = userinfo.GivenName, Lastname = userinfo.FamilyName, Name = userinfo.Name, Username = userinfo.PreferredUsername, ExternalProfileUrl = userinfo.Profile }; // simply auto-provisions new external user user = await identityUserService.AutoProvisionUser(toInsertuser); } // this allows us to collect any additional claims or properties // for the specific protocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. List <Claim> additionalLocalClaims = new List <Claim>(); AuthenticationProperties localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user IdentityServerUser isuser = new IdentityServerUser(user.SubjectId) { DisplayName = user.Name, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps) .ConfigureAwait(false); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme) .ConfigureAwait(false); // check if external login is in the context of an OIDC request AuthorizationRequest context = await interaction.GetAuthorizationContextAsync(returnUrl) .ConfigureAwait(false); await events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.ClientId)) .ConfigureAwait(false); if (context != null) { if (await clientStore.IsPkceClientAsync(context.ClientId) .ConfigureAwait(false)) { // 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(this.LoadingPage("Redirect", returnUrl)); } } return(Redirect(returnUrl)); }
public async Task <IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null) { returnUrl ??= this.Url.Content("~/"); if (remoteError != null) { this._logger.LogError($"External login error: {remoteError}"); return(this.LoginError(returnUrl, string.Format(LoginErrorConstants.ExternalRemoteError, remoteError))); } // read external identity from the temporary cookie var result = await this.HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme); if (result?.Succeeded != true) { this._logger.LogError($"External login error"); return(this.LoginError(returnUrl)); } if (this._logger.IsEnabled(LogLevel.Debug)) { this._logger.LogDebug("External claims: {@claims}", result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}")); } var info = await this._signInManager.GetExternalLoginInfoAsync(); if (info == null) { this._logger.LogError($"Configured external login information before the authentication is missing"); return(this.LoginError(returnUrl)); } var userId = info.Principal.Identity.Name; var user = await this._userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); if (user == null) { if (string.IsNullOrWhiteSpace(userId)) { this._logger.LogError($"External login with provider {info.LoginProvider} is success but the user principal name is missing"); return(this.LoginError(returnUrl)); } // Check for email claim in external authentication principal if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) { user = await this._userManager.FindByEmailAsync(info.Principal.FindFirstValue(ClaimTypes.Email)); } if (user == null || !user.IsActive) { return(this.UserNotRegistered(returnUrl, userId)); } // Map user to user logins var identityResult = await this._userManager.AddLoginAsync(user, new UserLoginInfo(info.LoginProvider, info.ProviderKey, info.ProviderDisplayName)); if (!identityResult.Succeeded) { this._logger.LogError($"External login with provider {info.LoginProvider} is success but mapping the user to userlogins is failed"); return(this.LoginError(returnUrl)); } } if (!user.IsActive) { return(this.UserNotRegistered(returnUrl, userId)); } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); this.ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user // we must issue the cookie maually, and can't use the SignInManager because // it doesn't expose an API to issue additional claims from the login workflow var principal = await this._signInManager.CreateUserPrincipalAsync(user); additionalLocalClaims.AddRange(principal.Claims); var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id; var isuser = new IdentityServerUser(user.Id) { DisplayName = name, IdentityProvider = info.LoginProvider, AdditionalClaims = additionalLocalClaims }; await this.HttpContext.SignInAsync(isuser, localSignInProps); await this._eventService.RaiseAsync(new UserLoginSuccessEvent(info.LoginProvider, info.ProviderKey, user.Id, name)); // delete temporary cookie used during external authentication await this.HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); // check if external login is in the context of an OIDC request var context = await this._interaction.GetAuthorizationContextAsync(returnUrl); await this._eventService.RaiseAsync(new UserLoginSuccessEvent(info.LoginProvider, info.ProviderKey, user.Id, user.Email, true, context?.Client.ClientId)); if (context != null) { if (context.IsNativeClient()) { // 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(this.RedirectToPage("/Redirect", new { RedirectUrl = returnUrl })); } } return(this.Redirect(returnUrl)); }
/// <summary> /// Signs the user in. /// </summary> /// <param name="context">The manager.</param> /// <param name="user">The IdentityServer user.</param> /// <param name="properties">The authentication properties.</param> /// <returns></returns> public static async Task SignInAsync(this HttpContext context, IdentityServerUser user, AuthenticationProperties properties) { await context.SignInAsync(await context.GetCookieAuthenticationSchemeAsync(), user.CreatePrincipal(), properties); }
public async Task <IActionResult> Login(LoginInputModel model, string button) { var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); _logger.LogInformation("displaying login options"); // 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 (await _clientStore.IsPkceClientAsync(context.Client.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) { ResourceOwnerPasswordValidationContext ValidationContext = new ResourceOwnerPasswordValidationContext { UserName = model.Username, Password = model.Password, }; _logger.LogInformation("Setting up validation context for user"); var passwordValidator = _resourceOwnerPasswordValidation as ResourceOwnerPasswordValidator; ValidationContext = await passwordValidator.ValidatePassword(ValidationContext); _logger.LogInformation("Validation process started"); // validate username/password against in-memory store if (ValidationContext.Result != null) { if (ValidationContext.Result.Subject != null) { if (ValidationContext.Result.Subject.Identity.IsAuthenticated) { _logger.LogInformation("Validation process succesfully retrieved authenticated user"); var user = _userRepository.FindUserByUsernameOrEmail(model.Username); await _events.RaiseAsync(new UserLoginSuccessEvent(model.Username, ValidationContext.Result.Subject.ToString(), model.Username)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; var claims = ProfileService.GetUserClaims(user); // issue authentication cookie with subject ID and username _logger.LogInformation("Issuing authentication cookie"); var isuser = new IdentityServerUser(user.UsersId.ToString()) { DisplayName = user.Username }; await HttpContext.SignInAsync(isuser, props); if (context != null) { if (await _clientStore.IsPkceClientAsync(context.Client.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 })); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(model.ReturnUrl)); } // request for a local page if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } else { // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } } } } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials")); ModelState.AddModelError(string.Empty, ValidationContext.Result.ErrorDescription); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie AuthenticateResult?result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception(Properties.Resources.ExternalAuthenticationError); } if (_logger.IsEnabled(LogLevel.Debug)) { IEnumerable <string>?externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); // External claims: {%1}. _logger.LogDebug(string.Format( CultureInfo.CurrentCulture, Properties.Resources.ExternalClaimsLog, string.Join(", ", externalClaims))); } // lookup our user and external provider info (TestUser user, string provider, string providerUserId, IEnumerable <Claim> claims) = FindUserFromExternalProvider(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration in // this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = AutoProvisionUser(provider, providerUserId, claims); } // this allows us to collect any additional claims or properties for the specific // protocols used and store them in the local auth cookie. this is typically used to // store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); //ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); //ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user var isuser = new IdentityServerUser(user.SubjectId) { DisplayName = user.Username, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL string?returnTo = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request AuthorizationRequest?context = await _interaction.GetAuthorizationContextAsync(returnTo); await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client?.ClientId)); if (context?.Client != null) { if (await _clientStore.IsPkceClientAsync(context.Client.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(this.LoadingPage("Redirect", returnTo)); } } return(Redirect(returnTo)); }
public async Task <string> GetAccessTokenAsync(UserModel user, List <Claim> additionalClientClaims = null, string userUuidOverride = null) { try { var tokenCreationRequest = new TokenCreationRequest(); var identityPricipal = await _principalFactory.CreateAsync(user).ConfigureAwait(false); var identityUser = new IdentityServerUser(!string.IsNullOrEmpty(userUuidOverride) ? userUuidOverride : user.Id.ToString()); identityUser.AdditionalClaims = identityPricipal.Claims.ToArray(); identityUser.DisplayName = user.UserName; identityUser.AuthenticationTime = DateTime.UtcNow; identityUser.IdentityProvider = IdentityServerConstants.LocalIdentityProvider; var subject = identityUser.CreatePrincipal(); tokenCreationRequest.Subject = subject; tokenCreationRequest.IncludeAllIdentityClaims = true; tokenCreationRequest.ValidatedRequest = new ValidatedRequest(); tokenCreationRequest.ValidatedRequest.Subject = tokenCreationRequest.Subject; string defaultClientId = _configurationProvider.DefaultClientId; var client = await _clientStore.FindClientByIdAsync(defaultClientId).ConfigureAwait(false); tokenCreationRequest.ValidatedRequest.SetClient(client); var resources = await _resourceStore.GetAllEnabledResourcesAsync().ConfigureAwait(false); tokenCreationRequest.Resources = resources; tokenCreationRequest.ValidatedRequest.Options = _options; if (additionalClientClaims != null) { foreach (Claim additionalClientClaim in additionalClientClaims) { tokenCreationRequest.ValidatedRequest.ClientClaims.Add(additionalClientClaim); } } var accessToken = await CreateAccessTokenAsync(tokenCreationRequest).ConfigureAwait(false); string defaultClientAuthority = _configurationProvider.DefaultClientAuthority; accessToken.Issuer = defaultClientAuthority; accessToken.Audiences = new string[] { _configurationProvider.DefaultClientAudience }; var accessTokenValue = await _tokenService.CreateSecurityTokenAsync(accessToken).ConfigureAwait(false); return(accessTokenValue); } catch (ApiException e) { throw e; } catch (Exception e) { _logger.LogError($"Error when getting access token: {e}"); throw new InternalServerErrorApiException(); } }
public async Task <IActionResult> Login(LoginInputModel model, string button) { _logger.LogInformation("Login. Email: {Email}, Remember login: {RememberLogin}.", model.Email, model.RememberLogin); // 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) { var user = await _userRepository.GetUserByEmailAsync(model.Email.ToLower()); var isHavePassword = !string.IsNullOrEmpty(user.HashPassword) && !string.IsNullOrEmpty(user.Salt); if (!user.IsEmpty() && isHavePassword) { _logger.LogInformation("Login. Found user by mail: id {Id}, name {Name}, Surname {Surname}, mail {Mail}.", user.Id, user.Name, user.Surname, user.Mail); //Validate found user if (_userService.ValidateCredentials(user, model.Password)) { _logger.LogInformation("Login. Validate Credentials was success. User: id {Id}, name {Name}, " + "Surname {Surname}, mail {Mail}.", user.Id, user.Name, user.Surname, user.Mail); await _events.RaiseAsync(new UserLoginSuccessEvent(user.Name, user.Id.ToString(), user.Name)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(user.Id.ToString()) { DisplayName = user.Name }; await HttpContext.SignInAsync(isuser, props); if (context != 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)); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(model.ReturnUrl)); } // request for a local page if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } else { // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } } else { _logger.LogWarning("Login. Validate Credentials was failed. User: id {Id}, name {Name}, " + "Surname {Surname}, mail {Mail}.", user.Id, user.Name, user.Surname, user.Mail); } _logger.LogWarning("Login. User with email {email} not exist.", model.Email.ToLower()); } await _events.RaiseAsync(new UserLoginFailureEvent(model.Email, "invalid credentials", clientId : context?.Client.ClientId)); ModelState.AddModelError(string.Empty, _localizer["Invalid_email_or_password"].Value); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }
public async Task <IdentityServerStoreAppliedInfo> CreateIdentityServerUserAsync(IdentityServerUser user) { var result = await TryWithAwaitInCatch.ExecuteAndHandleErrorAsync( async() => { await ResilientSessionContainer.EstablishSessionAsync(); return(await ResilientSessionContainer.ResilientSession.CreateIdentityServerUserAsync(user)); }, async (ex) => ResilientSessionContainer.HandleCassandraException <IdentityServerStoreAppliedInfo>(ex)); return(result); }
public async Task <IActionResult> OnGet() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } var externalUser = result.Principal; if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = externalUser.Claims.Select(c => $"{c.Type}: {c.Value}"); _logger.LogDebug("External claims: {@claims}", externalClaims); } // lookup our user and external provider info // try to determine the unique id of the external user (issued by the provider) // the most common claim type for that are the sub claim and the NameIdentifier // depending on the external provider, some other claim type might be used var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ?? externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? throw new Exception("Unknown userid"); var provider = result.Properties.Items["scheme"]; var providerUserId = userIdClaim.Value; // find external user var user = _users.FindByExternalProvider(provider, providerUserId); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user // // remove the user id claim so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); claims.Remove(userIdClaim); user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList()); } // this allows us to collect any additional claims or properties // for the specific protocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); CaptureExternalLoginContext(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user var isuser = new IdentityServerUser(user.SubjectId) { DisplayName = user.Username, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId)); if (context != 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(returnUrl)); } } return(Redirect(returnUrl)); }
public async Task <IActionResult> Login(LoginModel loginModel) { if (ModelState.IsValid) { var validCredentials = await AccountService.ValidateCredentials(loginModel); if (validCredentials) { // check if we are in the context of an authorization request var context = await InteractionService.GetAuthorizationContextAsync(loginModel.RedirectURL); var user = await UserService.GetUserByEmail(loginModel.Email); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. var props = default(AuthenticationProperties); if (loginModel.Remember) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(30)) }; } // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(user.Id) { DisplayName = user.Name, AdditionalClaims = user.Roles?.Select(role => new Claim(JwtClaimTypes.Role, role))?.ToList() ?? new System.Collections.Generic.List <Claim>() }; await HttpContextWrapper.SignInAsync(HttpContext, isuser, props); if (context != 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); //} // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(loginModel.RedirectURL)); } // request for a local page if (Url.IsLocalUrl(loginModel.RedirectURL)) { return(Redirect(loginModel.RedirectURL)); } else if (string.IsNullOrEmpty(loginModel.RedirectURL)) { return(Redirect("~/")); } else { // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } } } this.ModelState.AddModelError(INVALID_CREDENTIALS, "Invalid Credentials"); return(View(ControllerConstants.LOGIN, loginModel)); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); _logger.LogDebug("External claims: {@claims}", externalClaims); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = await AutoProvisionUserAsync(provider, providerUserId, claims); } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); //ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); //ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user // we must issue the cookie maually, and can't use the SignInManager because // it doesn't expose an API to issue additional claims from the login workflow var principal = await _signInManager.CreateUserPrincipalAsync(user); additionalLocalClaims.AddRange(principal.Claims); var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id; var isuser = new IdentityServerUser(user.Id) { DisplayName = name, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name, true, context?.ClientId)); if (context != 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(this.LoadingPage("Redirect", returnUrl)); } } return(Redirect(returnUrl)); }
public async Task <ActionResult> MakeAssertion([ModelBinder(typeof(NewtonsoftJsonAdapter.Binder))] MakeAssertionRequest request) { try { // 1. Get the assertion options we sent the client var jsonOptions = TestUsers.FidoAttestationOptions[request.SessionId]; var options = AssertionOptions.FromJson(jsonOptions); // 2. Get registered credential from database var creds = TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(request.RawResponse.Id)).FirstOrDefault(); if (creds == null) { return(BadRequest("unknown credentials")); } // 3. Get credential counter from database var storedCounter = creds.SignatureCounter; // 4. Create callback to check if userhandle owns the credentialId IsUserHandleOwnerOfCredentialIdAsync callback = async(args) => { var storedCreds = TestUsers.FidoCredentials.Where(c => c.UserHandle.SequenceEqual(args.UserHandle)); return(storedCreds.Any(c => c.Descriptor.Id.SequenceEqual(args.CredentialId))); }; // 5. Make the assertion var res = await _lib.MakeAssertionAsync( assertionResponse : request.RawResponse, originalOptions : options, storedPublicKey : creds.PublicKey, storedSignatureCounter : storedCounter, isUserHandleOwnerOfCredentialIdCallback : callback); // 6. Store the updated counter TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(res.CredentialId)).FirstOrDefault().SignatureCounter = res.Counter; // 7. return OK to client if (string.Equals(res.Status, "ok", StringComparison.InvariantCultureIgnoreCase)) { //actually loging the user in var context = await _interaction.GetAuthorizationContextAsync(request.ReturnUrl); var dbUser = TestUsers.Users.FirstOrDefault(u => string.Equals(u.SubjectId, creds.SubjectId, StringComparison.InvariantCultureIgnoreCase)); AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && request.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; var isuser = new IdentityServerUser(dbUser.SubjectId) { DisplayName = dbUser.Username }; await HttpContext.SignInAsync(isuser, props); if (context != null) { // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(this.NewtonsoftJsonResult(new MakeAssertionResponse { Status = "ok", Response = res, ReturnUrl = request.ReturnUrl })); } // request for a local page if (Url.IsLocalUrl(request.ReturnUrl)) { return(this.NewtonsoftJsonResult(new MakeAssertionResponse { Status = "ok", Response = res, ReturnUrl = request.ReturnUrl })); } else if (string.IsNullOrEmpty(request.ReturnUrl)) { return(this.NewtonsoftJsonResult(new MakeAssertionResponse { Status = "ok", Response = res, ReturnUrl = "~/" })); } else { // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } } else { return(BadRequest("not ok")); } } catch (Exception e) { return(BadRequest(new AssertionVerificationResult { Status = "error", ErrorMessage = FormatException(e) })); } }
public async Task <IResponseOutput> Login(LoginInput input) { if (!ModelState.IsValid) { return(ResponseOutput.NotOk(ModelState.Values.First().Errors[0].ErrorMessage)); } if (input.Captcha == null) { return(ResponseOutput.NotOk("请完成安全验证!")); } //滑动验证 input.Captcha.DeleteCache = true; using var client = new HttpClient(); var res = await client.GetAsync($"{_appSettings.Captcha.CheckUrl}?{ToParams(input.Captcha)}"); var content = await res.Content.ReadAsStringAsync(); var captchaResult = JsonConvert.DeserializeObject <ResultModel <string> >(content); if (!captchaResult.Success) { return(ResponseOutput.NotOk("安全验证不通过,请重新登录!")); } var sw = new Stopwatch(); sw.Start(); var context = await _interaction.GetAuthorizationContextAsync(input.ReturnUrl); var user = await _userRepository.Select.Where(a => a.UserName == input.UserName) .ToOneAsync(a => new { a.Id, a.Password, a.NickName, a.TenantId }); if (user == null) { return(ResponseOutput.NotOk("", 1)); } var password = MD5Encrypt.Encrypt32(input.Password); if (user.Password != password) { return(ResponseOutput.NotOk("", 2)); } AuthenticationProperties props = null; if (input.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1)) }; } ; var identityServerUser = new IdentityServerUser(user.Id.ToString()) { DisplayName = input.UserName }; await HttpContext.SignInAsync(identityServerUser, props); sw.Stop(); //写登录日志 var loginLogEntity = new LoginLogEntity() { Id = YitIdHelper.NextId(), TenantId = user.TenantId, CreatedUserId = user.Id, NickName = user.NickName, CreatedUserName = input.UserName, ElapsedMilliseconds = sw.ElapsedMilliseconds, Status = true }; await AddLoginLog(loginLogEntity); return(ResponseOutput.Ok()); }
public async Task<IActionResult> Login(LoginInputModel model, string button) { if (button != "login") { // the user clicked the "cancel" button var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); 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 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) { var user = await _userManager.FindByNameAsync(model.Username); if (user != null && await _userManager.CheckPasswordAsync(user, model.Password)) { await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; }; var isuser = new IdentityServerUser(user.Id) { DisplayName = user.UserName, AdditionalClaims = new List<Claim> { new Claim("AspNet.Identity.SecurityStamp", user.SecurityStamp) } }; // issue authentication cookie with subject ID and username await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName)); await HttpContext.SignInAsync(isuser, props); // make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl)) { return Redirect(model.ReturnUrl); } return Redirect("~/"); } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials")); ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error var vm = await _account.BuildLoginViewModelAsync(model); return View(vm); }
public async Task <IActionResult> Callback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); _logger.LogDebug("External claims: {@claims}", externalClaims); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user user = AutoProvisionUser(provider, providerUserId, claims); } // this allows us to collect any additional claims or properties // for the specific protocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user var isuser = new IdentityServerUser(user.Id.ToString()) { DisplayName = user.UserName, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims, }; await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), user.UserName, true, context?.Client.ClientId)); if (context != 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", returnUrl)); } } return(Redirect(returnUrl)); }
public Task SignInAsync(HttpContext httpContext, IdentityServerUser user, AuthenticationProperties properties) { return(httpContext.SignInAsync(user, properties)); }
public async Task <IResponseOutput> Login(LoginInputModel input) { if (!ModelState.IsValid) { return(ResponseOutput.NotOk(ModelState.Values.First().Errors[0].ErrorMessage)); } var sw = new Stopwatch(); sw.Start(); // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(input.ReturnUrl); var user = await _userRepository.Select.Where(a => a.UserName == input.UserName) .ToOneAsync(a => new { a.Id, a.Password, a.NickName }); if (user == null) { return(ResponseOutput.NotOk("", 1)); } var password = MD5Encrypt.Encrypt32(input.Password); if (user.Password != password) { return(ResponseOutput.NotOk("", 2)); } await _events.RaiseAsync(new UserLoginSuccessEvent(input.UserName, user.Id.ToString(), input.UserName, clientId : context?.ClientId)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && input.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(user.Id.ToString()) { DisplayName = input.UserName }; await HttpContext.SignInAsync(isuser, props); sw.Stop(); //写登录日志 var loginLogEntity = new LoginLogEntity() { CreatedUserId = user.Id, NickName = user.NickName, CreatedUserName = input.UserName, ElapsedMilliseconds = sw.ElapsedMilliseconds, Status = true }; await AddLoginLog(loginLogEntity); return(ResponseOutput.Ok()); /* * if (context != 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 this.LoadingPage("Redirect", input.ReturnUrl); * } * * // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null * return Redirect(input.ReturnUrl); * } * * // request for a local page * if (Url.IsLocalUrl(input.ReturnUrl)) * { * return Redirect(input.ReturnUrl); * } * else if (string.IsNullOrEmpty(input.ReturnUrl)) * { * return Redirect("~/"); * } * else * { * // user might have clicked on a malicious link - should be logged * throw new Exception("invalid return URL"); * } * * await _events.RaiseAsync(new UserLoginFailureEvent(input.UserName, "invalid credentials", clientId: context?.ClientId)); * ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); */ }
public async Task <IActionResult> Login(LoginInputModel model, string button) { // 检查我们是否在授权请求的上下文中 var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); // 用户单击“取消”按钮 if (button != "login") { if (context != null) { //如果用户取消,则将结果发送到身份服务器,就像 // 拒绝同意(即使该客户不需要同意)。 // 这将向客户端发回一个被拒绝的oidc错误响应。 await _interaction.GrantConsentAsync(context, ConsentResponse.Denied); // 我们可以信任模特。因为GetAuthorizationContextAsync回来了 if (await _clientStore.IsPkceClientAsync(context.ClientId)) { // 如果客户端是pkce,那么我们假设它是本地的,因此在如何 // 返回响应是为了最终用户获得更好的ux。 return(View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl })); } return(Redirect(model.ReturnUrl)); } else { // 既然我们没有一个有效的上下文,那么我们就回到主页 return(Redirect("~/")); } } if (ModelState.IsValid) { //查找用户 //var user = _userApp.GetUser(model.Username); var requestUri = "http://localhost:61927/api/Account"; var response = MyHttp.Post(requestUri, null, model); CJ.Models.LoginInputModel user = new CJ.Models.LoginInputModel(); if (!string.IsNullOrEmpty(response.Data)) { user = JsonConvert.DeserializeObject <CJ.Models.LoginInputModel>(response.Data); } else { user = null; }; //对内存中的用户名/密码进行验证 if (user != null && (model.Password == DESCrypt.Decrypt(user.Password))) { await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.Id, user.Username)); // 如果用户选择“记住我”,只在此设置显式过期。 // 否则,我们将依赖于Cookie中间件中配置的过期。 AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, //认证信息是否跨域有效 ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) //凭据有效时间 }; } ; var serverUser = new IdentityServerUser(user.Id); serverUser.DisplayName = user.DisplayName; var claims = new[] { new Claim("Username", user.Username), new Claim("DisplayName", user.DisplayName) }; serverUser.AdditionalClaims = claims; // issue authentication cookie with subject ID and username await HttpContext.SignInAsync(serverUser); if (context != null) { if (await _clientStore.IsPkceClientAsync(context.ClientId)) { // 如果客户端是pkce,那么我们假设它是本地的,所以在如何 // 返回的响应是为最终用户提供更好的ux。 return(View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl })); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(model.ReturnUrl)); } //请求本地页 if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } else { // 用户可能点击了恶意链接-应该被记录 throw new Exception("无效的返回URL"); } } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "无效的凭据")); ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } // 出了问题,显示形式错误 var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }