我正在尝试存储来自外部登录声明的新用户数据。
我只想说我有一个模特
public class User
{
Guid UniqueIdentifier;
string Username;
string Firstname;
string LastName;
string Email;
Date DateOfBirth;
}
以及将用户添加到数据库的方法:
_userService.Add(new User());
这是他们永久登录回拨的标准IdentityServer实现。
[HttpGet]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
{
// read external identity from the temporary cookie
var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
var tempUser = info?.Principal;
if (tempUser == null)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var claims = tempUser.Claims.ToList();
// try to determine the unique id of the external user - 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 = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
if (userIdClaim == null)
{
userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
}
if (userIdClaim == null)
{
throw new Exception("Unknown userid");
}
// remove the user id claim from the claims collection and move to the userId property
// also set the name of the external authentication provider
claims.Remove(userIdClaim);
var provider = info.Properties.Items["scheme"];
var userId = userIdClaim.Value;
// check if the external user is already provisioned
var user = await _userManager.FindByLoginAsync(provider, userId);
if (user == null)
{
user = new IdentityUser { UserName = Guid.NewGuid().ToString()
};
await _userManager.CreateAsync(user);
await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, userId, provider));
}
var additionalClaims = new List<Claim>();
// if the external system sent a session id claim, copy it over
var sid = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
if (sid != null)
{
additionalClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));
}
// issue authentication cookie for user
await HttpContext.Authentication.SignInAsync(user.Id, user.UserName, provider, additionalClaims.ToArray());
// delete temporary cookie used during external authentication
await HttpContext.Authentication.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
// validate return URL and redirect back to authorization endpoint
if (_interaction.IsValidReturnUrl(returnUrl))
{
return Redirect(returnUrl);
}
return Redirect("~/");
}
我的问题是如何为每个登录用户检索唯一标识符?假设用户通过谷歌登录,我不能将他们的电子邮件地址用作唯一ID,因为他们可能已经使用其他提供商的电子邮件进行了注册?
答案 0 :(得分:0)
您可能需要构建某种形式的标识符,该标识符来自外部提供程序发出的令牌。在OpenID Connect中,假定主题声明在本地对提供者唯一。构造全局唯一标识符的一种方法是制作某种复合键(或构造键),该键使用发行者(iss
)声明和主题(sub
)声明的声明,标识符通常保证全局唯一。