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"); } // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // lookup our user and external provider info var(user, provider, providerUserId, claims) = await FindUserFromExternalProvider(result); foreach (var claim in claims) { _logger.LogInformation($"External provider[{provider}] info-> claim:{claim.Type}, value:{claim.Value}"); } if (user == null) { // user wasn't found by provider, but maybe one exists with the same email address? if (provider == "Google" || provider == "Facebook") { // email claim from Google var email = claims.FirstOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"); if (email != null) { var userByEmail = await _usersService.GetUserByEmailAsync(email.Value); if (userByEmail != null) { // add Google as a provider for this user await _usersService.AddUserLoginAsync(userByEmail.SubjectId, provider, providerUserId); // redirect to ExternalLoginCallback var continueWithUrlAfterAddingUserLogin = Url.Action("Callback", new { returnUrl = returnUrl }); return(Redirect(continueWithUrlAfterAddingUserLogin)); } } } var returnUrlAfterRegistration = Url.Action("Callback", new { returnUrl = returnUrl }); var continueWithUrl = Url.Action("RegisterUser", "UserRegistration", new { returnUrl = returnUrlAfterRegistration, provider = provider, providerUserId = providerUserId }); return(Redirect(continueWithUrl)); } // 2-F.A var id = new ClaimsIdentity(); id.AddClaim(new Claim(JwtClaimTypes.Subject, user.SubjectId)); await HttpContext.SignInAsync(scheme : Startup.TwoFactorAuthenticationScheme, principal : new ClaimsPrincipal(id)); await _twoFactorAuthenticationService.SendTemporaryCodeAsync(user.SubjectId); var redirectToAdditionalFactorUrl = Url.Action("AdditionalAuthenticationFactor", new { returnUrl = returnUrl, rememberLogin = false, provider = provider, providerUserId = providerUserId }); if (Url.IsLocalUrl(returnUrl)) { return(Redirect(redirectToAdditionalFactorUrl)); } if (string.IsNullOrEmpty(returnUrl)) { return(Redirect("~/")); } // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); }