How to create identity user based on claims prinicpals

I am using asp.net mvc with work/school accounts authentication. Currently I’m trying to implement identity into to the user process.

Here is my ApplicationUser class:

public class ApplicationUser: IdentityUser
{
    public ICollection<Semester> Semesters { get; set; }
}

So far, identity works just fine, there is just one problem. When I log into the app with my school account, I can call the ClaimsPrincipals as User in the Controllers. To get the current ApplicationUser you can use the UserManager (await _userManager.GetUserAsync(User), with User being the ClaimsPrincipals) But since I haven’t stored my school account in the database, the result will be null. If I create a new ApplicationUser like the following

var newUser = new ApplicationUser()
{
    UserName = User.Identity.Name,
    Email = User.Identity.Name
};
await _userManager.CreateAsync(newUser);
await _userManager.AddClaimsAsync(newUser, User.Claims);

This will succesfully create and save the new user to the database with the claims. But then when I try to get the new created ApplicationUser with await _userManager.GetUserAsync(User) the result will still be null. If I access my DbContext and get all ApplicationUsers, the newly created ApplicationUser is there. So, how can I create an ApplicationUser based on the ClaimsPrincipals I get from my school account login?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Credits to @poke for this.

UserManager.GetUserAsync internally uses UserManager.GetUserId to retrieve the user id of the user which is then used to query the object from the user store (i.e. your database).

GetUserId basically looks like this:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}

So this returns the claim value of Options.ClaimsIdentity.UserIdClaimType. Options is the IdentityOptions object that you configure Identity with. By default the value of UserIdClaimType is ClaimTypes.NameIdentifier, i.e. "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

So when you try to use UserManager.GetUserAsync(HttpContext.User), where that user principal has a UserID claim, the user manager is simply looking for a different claim.

You can fix this by either switchting to the ClaimTypes.NameIdentifier:

new ClaimsIdentity(new[]
{
    new Claim(ClaimTypes.Name, user.UserName),
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
})

Or you configure Identity properly so it will use your UserID claim type:

// in Startup.ConfigureServices
services.AddIdentity(options => {
    options.ClaimIdentity.UserIdClaimType = "UserID";
});

Source:

https://stackoverflow.com/a/51122850/3850405

Method 2

The claims from an external provider will be specific to that provider. It is not logging into the local identity store in your app, it is just claiming to know who the user is. So you need to log the user to your store (SignInManager) before you can use it for authorization. If you don’t care about protecting resources and just want to know the user you can directly map to your internal store

The claims in the header need to be intercepted by the ASPNET ‘middleware’ using an authentication provider which will then set the User object in the HttpContext. Once you have the user, you would need to map your local user store to those from the school account, then get the claims as a separate call from the result. Usually the email is the subject claim and can be used for mapping:

    var userName = User.Identity.Name;
    var user = _userManager.FindByNameAsync(userName);
    var claims = _userManager.GetClaimsAsync(user);


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x