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); } // check to see if user clicked "remember me" on login page bool?rememberMe = await context.GetPartialLoginRememberMeAsync(); return(await SignInAndRedirectAsync(signInMessage, signInId, result, rememberMe)); }