private async Task <(EMUsers user, string provider, string providerUserId, IEnumerable <Claim> claims)> FindUserFromExternalProviderAsync(AuthenticateResult result) { var externalUser = result.Principal; // 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"); // 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); var provider = result.Properties.Items["scheme"]; var providerUserId = userIdClaim.Value; // find external user var user = await _userManager.FindByLoginAsync(provider, providerUserId); // try to find user by name and/or email if (user == null) { var name = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value ?? claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value; if (name != null) { user = await _userManager.FindByNameAsync(name); } if (user == null) { var prefname = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.PreferredUserName)?.Value; if (prefname != null) { user = await _userManager.FindByNameAsync(prefname); } } if (user == null) { var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ?? claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value; if (email != null) { user = await _userManager.FindByEmailAsync(email); } } if (user != null) { var identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider)); if (!identityResult.Succeeded) { throw new Exception(identityResult.Errors.First().Description); } } } return(user, provider, providerUserId, claims); }
private async Task <EMUsers> AutoProvisionUserAsync(string provider, string providerUserId, IEnumerable <Claim> claims) { // create a list of claims that we want to transfer into our store var filtered = new List <Claim>(); // user's display name var name = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value ?? claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value; if (name != null) { filtered.Add(new Claim(JwtClaimTypes.Name, name)); } else { var first = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.GivenName)?.Value ?? claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value; var last = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.FamilyName)?.Value ?? claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value; if (first != null && last != null) { filtered.Add(new Claim(JwtClaimTypes.Name, first + " " + last)); } else if (first != null) { filtered.Add(new Claim(JwtClaimTypes.Name, first)); } else if (last != null) { filtered.Add(new Claim(JwtClaimTypes.Name, last)); } } // email var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ?? claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value; if (email != null) { filtered.Add(new Claim(JwtClaimTypes.Email, email)); } var user = new EMUsers { UserName = Guid.NewGuid().ToString(), }; var identityResult = await _userManager.CreateAsync(user); if (!identityResult.Succeeded) { throw new Exception(identityResult.Errors.First().Description); } if (filtered.Any()) { identityResult = await _userManager.AddClaimsAsync(user, filtered); if (!identityResult.Succeeded) { throw new Exception(identityResult.Errors.First().Description); } } identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider)); if (!identityResult.Succeeded) { throw new Exception(identityResult.Errors.First().Description); } return(user); }