public override Task AuthenticateLocalAsync(LocalAuthenticationContext context) { var username = context.UserName; var password = context.Password; var message = context.SignInMessage; if (message != null) { var tenant = message.Tenant; if (username == password) { var claims = new List<Claim> { new Claim("account_store", tenant) }; var result = new AuthenticateResult("123", username, claims: claims, authenticationMethod: "custom"); context.AuthenticateResult = new AuthenticateResult("123", username, claims); } } return Task.FromResult(0); }
/// <summary> /// Updates the partial login with the authentication values provided. /// </summary> /// <param name="env">The env.</param> /// <param name="subject">The subject.</param> /// <param name="name">The name.</param> /// <param name="claims">The claims.</param> /// <param name="identityProvider">The identity provider.</param> /// <param name="authenticationMethod">The authentication method.</param> /// <returns></returns> public static async Task UpdatePartialLoginClaimsAsync( this IDictionary <string, object> env, string subject, string name, IEnumerable <Claim> claims = null, string identityProvider = Constants.BuiltInIdentityProvider, string authenticationMethod = null ) { if (env == null) { throw new ArgumentNullException("env"); } var authResult = new IdentityServer3.Core.Models.AuthenticateResult(subject, name, claims, identityProvider, authenticationMethod); await env.UpdatePartialLoginClaimsAsync(authResult.User.Claims); }
private void ClearAuthenticationCookiesForNewSignIn(AuthenticateResult authResult) { // on a partial sign-in, preserve the existing primary sign-in if (!authResult.IsPartialSignIn) { context.Authentication.SignOut(Constants.PrimaryAuthenticationType); } context.Authentication.SignOut( Constants.ExternalAuthenticationType, Constants.PartialSignInAuthenticationType); }
private Uri GetRedirectUrl(SignInMessage signInMessage, AuthenticateResult authResult) { if (signInMessage == null) throw new ArgumentNullException("signInMessage"); if (authResult == null) throw new ArgumentNullException("authResult"); if (authResult.IsPartialSignIn) { var path = authResult.PartialSignInRedirectPath; if (path.StartsWith("~/")) { path = path.Substring(2); path = Request.GetIdentityServerBaseUrl() + path; } var host = new Uri(context.GetIdentityServerHost()); return new Uri(host, path); } else { return new Uri(signInMessage.ReturnUrl); } }
private void IssueAuthenticationCookie(string signInMessageId, AuthenticateResult authResult, bool? rememberMe = null) { if (authResult == null) throw new ArgumentNullException("authResult"); if (authResult.IsPartialSignIn) { Logger.Info("issuing partial signin cookie"); } else { Logger.Info("issuing primary signin cookie"); } var props = new Microsoft.Owin.Security.AuthenticationProperties(); var id = authResult.User.Identities.First(); if (authResult.IsPartialSignIn) { // add claim so partial redirect can return here to continue login // we need a random ID to resume, and this will be the query string // to match a claim added. the claim added will be the original // signIn ID. var resumeId = CryptoRandom.CreateUniqueId(); var resumeLoginUrl = context.GetPartialLoginResumeUrl(resumeId); var resumeLoginClaim = new Claim(Constants.ClaimTypes.PartialLoginReturnUrl, resumeLoginUrl); id.AddClaim(resumeLoginClaim); id.AddClaim(new Claim(GetClaimTypeForResumeId(resumeId), signInMessageId)); // add url to start login process over again (which re-triggers preauthenticate) var restartUrl = context.GetPartialLoginRestartUrl(signInMessageId); id.AddClaim(new Claim(Constants.ClaimTypes.PartialLoginRestartUrl, restartUrl)); } else { signInMessageCookie.Clear(signInMessageId); sessionCookie.IssueSessionId(rememberMe); } if (!authResult.IsPartialSignIn) { // don't issue persistnt cookie if it's a partial signin if (rememberMe == true || (rememberMe != false && this.options.AuthenticationOptions.CookieOptions.IsPersistent)) { // only issue persistent cookie if user consents (rememberMe == true) or // if server is configured to issue persistent cookies and user has not explicitly // denied the rememberMe (false) // if rememberMe is null, then user was not prompted for rememberMe props.IsPersistent = true; if (rememberMe == true) { var expires = DateTimeHelper.UtcNow.Add(options.AuthenticationOptions.CookieOptions.RememberMeDuration); props.ExpiresUtc = new DateTimeOffset(expires); } } } context.Authentication.SignIn(props, id); }
private async Task<Tuple<IHttpActionResult, AuthenticateResult>> PostAuthenticateAsync(SignInMessage signInMessage, AuthenticateResult result) { if (result.IsPartialSignIn == false) { Logger.Info("Calling PostAuthenticateAsync on the user service"); var ctx = new PostAuthenticationContext { SignInMessage = signInMessage, AuthenticateResult = result }; await userService.PostAuthenticateAsync(ctx); var authResult = ctx.AuthenticateResult; if (authResult == null) { Logger.Error("user service PostAuthenticateAsync returned a null AuthenticateResult"); return new Tuple<IHttpActionResult,AuthenticateResult>(RenderErrorPage(), null); } if (authResult.IsError) { Logger.WarnFormat("user service PostAuthenticateAsync returned an error message: {0}", authResult.ErrorMessage); return new Tuple<IHttpActionResult, AuthenticateResult>(RenderErrorPage(authResult.ErrorMessage), null); } if (result != authResult) { result = authResult; Logger.Info("user service PostAuthenticateAsync returned a different AuthenticateResult"); } } return new Tuple<IHttpActionResult, AuthenticateResult>(null, result); }
private async Task<IHttpActionResult> SignInAndRedirectAsync(SignInMessage signInMessage, string signInMessageId, AuthenticateResult authResult, bool? rememberMe = null) { var postAuthenActionResult = await PostAuthenticateAsync(signInMessage, authResult); if (postAuthenActionResult != null) { if (postAuthenActionResult.Item1 != null) { return postAuthenActionResult.Item1; } if (postAuthenActionResult.Item2 != null) { authResult = postAuthenActionResult.Item2; } } ClearAuthenticationCookiesForNewSignIn(authResult); IssueAuthenticationCookie(signInMessageId, authResult, rememberMe); var redirectUrl = GetRedirectUrl(signInMessage, authResult); Logger.InfoFormat("redirecting to: {0}", redirectUrl); return Redirect(redirectUrl); }
public async Task<IHttpActionResult> ResumeLoginFromRedirect(string resume) { Logger.Info("Callback requested to resume login from partial login"); if (resume.IsMissing()) { Logger.Error("no resumeId passed"); return RenderErrorPage(); } if (resume.Length > MaxSignInMessageLength) { Logger.Error("resumeId length longer than allowed length"); return RenderErrorPage(); } var user = await context.GetIdentityFromPartialSignIn(); if (user == null) { Logger.Error("no identity from partial login"); return RenderErrorPage(); } var type = GetClaimTypeForResumeId(resume); var resumeClaim = user.FindFirst(type); if (resumeClaim == null) { Logger.Error("no claim matching resumeId"); return RenderErrorPage(); } var signInId = resumeClaim.Value; if (signInId.IsMissing()) { Logger.Error("No signin id found in resume claim"); return RenderErrorPage(); } var signInMessage = signInMessageCookie.Read(signInId); if (signInMessage == null) { Logger.Error("No cookie matching signin id found"); return RenderErrorPage(); } AuthenticateResult result = null; // determine which return path the user is taking -- are they coming from // a ExternalProvider partial logon, or not var externalProviderClaim = user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId); // cleanup the claims from the partial login if (user.HasClaim(c => c.Type == Constants.ClaimTypes.PartialLoginRestartUrl)) { user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.PartialLoginRestartUrl)); } if (user.HasClaim(c => c.Type == Constants.ClaimTypes.PartialLoginReturnUrl)) { user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.PartialLoginReturnUrl)); } if (user.HasClaim(c => c.Type == Constants.ClaimTypes.ExternalProviderUserId)) { user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId)); } if (user.HasClaim(c => c.Type == GetClaimTypeForResumeId(resume))) { user.RemoveClaim(user.FindFirst(GetClaimTypeForResumeId(resume))); } if (externalProviderClaim != null) { Logger.Info("using ExternalProviderUserId to call AuthenticateExternalAsync"); var provider = externalProviderClaim.Issuer; var providerId = externalProviderClaim.Value; var externalIdentity = new ExternalIdentity { Provider = provider, ProviderId = providerId, Claims = user.Claims }; Logger.InfoFormat("external user provider: {0}, provider ID: {1}", externalIdentity.Provider, externalIdentity.ProviderId); var externalContext = new ExternalAuthenticationContext { ExternalIdentity = externalIdentity, SignInMessage = signInMessage }; await userService.AuthenticateExternalAsync(externalContext); result = externalContext.AuthenticateResult; if (result == null) { Logger.Warn("user service failed to authenticate external identity"); var msg = localizationService.GetMessage(MessageIds.NoMatchingExternalAccount); await eventService.RaiseExternalLoginFailureEventAsync(externalIdentity, signInId, signInMessage, msg); return await RenderLoginPage(signInMessage, signInId, msg); } if (result.IsError) { Logger.WarnFormat("user service returned error message: {0}", result.ErrorMessage); await eventService.RaiseExternalLoginFailureEventAsync(externalIdentity, signInId, signInMessage, result.ErrorMessage); return await RenderLoginPage(signInMessage, signInId, result.ErrorMessage); } Logger.Info("External identity successfully validated by user service"); await eventService.RaiseExternalLoginSuccessEventAsync(externalIdentity, signInId, signInMessage, result); } else { // check to see if the resultant user has all the claim types needed to login if (!Constants.AuthenticateResultClaimTypes.All(claimType => user.HasClaim(c => c.Type == claimType))) { Logger.Error("Missing AuthenticateResultClaimTypes -- rendering error page"); return RenderErrorPage(); } // this is a normal partial login continuation Logger.Info("Partial login resume success -- logging user in"); result = new AuthenticateResult(new ClaimsPrincipal(user)); await eventService.RaisePartialLoginCompleteEventAsync(result.User.Identities.First(), signInId, signInMessage); } return await SignInAndRedirectAsync(signInMessage, signInId, result); }
/// <summary> /// Updates the partial login with the authentication values provided. /// </summary> /// <param name="env">The env.</param> /// <param name="subject">The subject.</param> /// <param name="name">The name.</param> /// <param name="claims">The claims.</param> /// <param name="identityProvider">The identity provider.</param> /// <param name="authenticationMethod">The authentication method.</param> /// <returns></returns> public static async Task UpdatePartialLoginClaimsAsync( this IDictionary<string, object> env, string subject, string name, IEnumerable<Claim> claims = null, string identityProvider = Constants.BuiltInIdentityProvider, string authenticationMethod = null ) { if (env == null) throw new ArgumentNullException("env"); var authResult = new IdentityServer3.Core.Models.AuthenticateResult(subject, name, claims, identityProvider, authenticationMethod); await env.UpdatePartialLoginClaimsAsync(authResult.User.Claims); }
private async Task<IHttpActionResult> SignInAndRedirectAsync(SignInMessage signInMessage, string signInMessageId, AuthenticateResult authResult, bool? rememberMe = null) { var postAuthenActionResult = await PostAuthenticateAsync(signInMessage, authResult); if (postAuthenActionResult != null) { if (postAuthenActionResult.Item1 != null) { return postAuthenActionResult.Item1; } if (postAuthenActionResult.Item2 != null) { authResult = postAuthenActionResult.Item2; } } // check to see if idp used to signin matches if (signInMessage.IdP.IsPresent() && authResult.IsPartialSignIn == false && authResult.HasSubject && authResult.User.GetIdentityProvider() != signInMessage.IdP) { // this is an error -- the user service did not set the idp to the one requested Logger.ErrorFormat("IdP requested was: {0}, but the user service issued signin for IdP: {1}", signInMessage.IdP, authResult.User.GetIdentityProvider()); return RenderErrorPage(); } ClearAuthenticationCookiesForNewSignIn(authResult); IssueAuthenticationCookie(signInMessageId, authResult, rememberMe); var redirectUrl = GetRedirectUrl(signInMessage, authResult); Logger.InfoFormat("redirecting to: {0}", redirectUrl); return Redirect(redirectUrl); }