Identity Server 4 Register Users from External Providers

こ雲淡風輕ζ 提交于 2019-12-25 07:46:51

问题


I'm trying to store new users data from the claims return from an external login.

lets just say I have a model

public class User
{
    Guid UniqueIdentifier;
    string Username;
    string Firstname;
    string LastName;
    string Email;
    Date DateOfBirth;
}

and a method to add a user to the Database:

_userService.Add(new User()); 

This is the standard IdentityServer implementation for their eternal login call back.

[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("~/");
}

My question is how can I retrieve a unique Identifier for each user that logs in? Say a user logs in via google, I Cannot use their email address as a unique id because they potentially could already have registered using that email from another provider?


回答1:


You might need to construct some form of identifier that comes from the token issued from the external provider. In OpenID Connect the subject claim is assumed to be locally unique to the provider. One way to construct a globally unique identifier is to make some sort of composite key (or constructed key) that uses both the issuer (iss) claim and the subject (sub) claim of the token, this identifier is generally guaranteed to be globally unique.



来源:https://stackoverflow.com/questions/42743078/identity-server-4-register-users-from-external-providers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!