Identity Server 4从外部供应商注册用户

时间:2017-03-12 02:35:16

标签: c# authentication identityserver4 claims

我正在尝试存储来自外部登录声明的新用户数据。

我只想说我有一个模特

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,因为他们可能已经使用其他提供商的电子邮件进行了注册?

1 个答案:

答案 0 :(得分:0)

您可能需要构建某种形式的标识符,该标识符来自外部提供程序发出的令牌。在OpenID Connect中,假定主题声明在本地对提供者唯一。构造全局唯一标识符的一种方法是制作某种复合键(或构造键),该键使用发行者(iss)声明和主题(sub)声明的声明,标识符通常保证全局唯一。