DarioN1
DarioN1

Reputation: 2552

Asp Net Identity - Claim vs Customized IdentityUser

I'm a bit confused on what is the best way to customize the user profile in order to implement custom logic in the application.

Suppose you have to profile the user with this kind of attributes:

Where do I have to implement this kind of attributes? Do I have to customize IdentityUser (using ApplicationUser) or do I have to create custom claims?

Upvotes: 4

Views: 2459

Answers (2)

Yahoo Serious
Yahoo Serious

Reputation: 3908

(Accidentally ran into this, and maybe this related answer is also useful for someone.)
As Gaelsa already mentioned, it's a matter of preference. I would say, that my main consideration would be:

  • Properties for which ASP.NET Identity is your primary source of user data should be strongly typed database columns (typically in AspNetUsers) and propagated to claims (when necessary) when creating the principal.
  • Properties imported and updated from another source can be propagated to claims in the DB (AspNetUsersClaims) right away.

Example:

  • if CanSendEmail is a property entered and changed by the user in this identity-interface, I would store it in a strongly typed database column in AspNetUsers.
  • if CanSendEmail is a property maintained in another application and updated from there, I would store it as a record in the claims-table, thus in AspNetUsersClaims.

FWIW: Saving additional user-properties, does not add them as a claim automatically. You could propagate them on save by deriving from UserClaimsPrincipalFactory<TUser>, and override CreateAsync (see this answer).
Or maybe you could add, it when claims are requested and generated (I think, no example at hand).

Upvotes: 0

GaelSa
GaelSa

Reputation: 600

Both approach are viable, and one could argue it's a matter of preference.

I would say using only added proprerties in the IdentityUser implementation is easier to access and also require less code.

Performance wise, I would argue that the more users and data needed to be added, the better the Proprerties and so DB storage make sense, using cookies can be faster, but depanding on use and server configuration for a large amount of data especially if you want to store a lot of information for each users can proove better in the long run.

You also have to take into account data persistance if one the following is true, you will have to use Proprerties.

  • the data need to be stored indefinitly
  • the data can or must be accessed if the user is not logged in.

After that, it's really a matter of taste and specific need in your application.

Considering your example you can use IdentityUser proprerties only:

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity>GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(this,  DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    }

    //There you can use display name or any attributes like a regular Model.
    public LevelEnum Level { get; set; }
    [Display(Name = "Is allowed to process")]
    public bool CanProcess { get; set; }
    public bool CanWorkOffline { get; set; }
    public bool CanSendEmail { get; set; }
    public bool CanViewFullName { get; set; }
}

then you can access the proprerties in your controler really easily:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
viewModel.Level = user.Level;

same way to set

user.Level = viewModel.Level;

and saving the user using UserManager:

await _userManager.UpdateAsync(user);
//or to create
await UserManager.CreateAsync(user, model.Password);

As for the claim approach:

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

        // Add custom user claims here 
        userIdentity.AddClaim(new Claim("Level", LevelEnum.Default));

        return userIdentity;
    }

then to access:

//claim can be null.
var claim = ((ClaimsIdentity)identity).FirstOrDefault("Level") ?? LevelEnum.Default;

And also of course, you can db stored properties to the claims if needed. Using the example for Propreties above:

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

        // Add custom user claims here 
        userIdentity.AddClaim(new Claim(nameof(Level), Level));

        return userIdentity;
    }

Upvotes: 5

Related Questions