Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing custom claim with extended MVC Core Identity user

How can I create a custom authorize claim in MVC Core 2.0 (using AspNetCore.identity) to verify a custom user boolean property? I have extended the IdentityUser (ApplicationUser) to include a boolean value "IsDeveloper". I am using claims based authentication and would like to add a custom claim, but am not certain where to start. How can I create a custom claim that will:

  1. Find the current (customized) Core.Identity user.
  2. Evaluate the a custom identity user bool value?

I understand the core identity claims MSDN: Claims Based Authentication, but am new to custom claims, so I am not sure where to begin. The Online documents that I have found do not work or does not fit my scenario.

like image 842
davewilliams459 Avatar asked Feb 06 '18 21:02

davewilliams459


People also ask

How would you implement claims-based authentication in .NET core?

The claims-based authorization works by checking if the user has a claim to access an URL. In ASP.NET Core we create policies to implement the Claims-Based Authorization. The policy defines what claims that user must process to satisfy the policy. We apply the policy on the Controller, action method, razor page, etc.

What is claims identity .NET core?

Claims can be created from any user or identity data which can be issued using a trusted identity provider or ASP.NET Core identity. A claim is a name value pair that represents what the subject is, not what the subject can do.


1 Answers

So, you need to create custom claims somewhere and then check it through a custom policy or manually.

1) Custom claims adding

JwtBearer authentication

You can do something like this:

In your controller action that returns jwt-token you can add your custom claim:

[HttpGet]
public dynamic GetToken(string login, string password)
{
    var handler = new JwtSecurityTokenHandler();

    var sec = "12312313212312313213213123123132123123132132132131231313212313232131231231313212313213132123131321313213213131231231213213131311";
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(sec));
    var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

    var user = GetUserFromDb(login);
    var identity = new ClaimsIdentity(new GenericIdentity(user.Email), new[] { new Claim("user_id", user.Id) });
    if (user.IsDeveloper)
        identity.AddClaim(new Claim("IsDeveloper", "true"));
    var token = handler.CreateJwtSecurityToken(subject: identity,
                                                signingCredentials: signingCredentials,
                                                audience: "ExampleAudience",
                                                issuer: "ExampleIssuer",
                                                expires: DateTime.UtcNow.AddSeconds(100));
    return handler.WriteToken(token);
}

ASP.NET Core Identity authentication

You need to implement a custom IUserClaimsPrincipalFactory or use UserClaimsPrincipalFactory as a base class:

public class ApplicationClaimsIdentityFactory: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory <ApplicationUser>
{
    UserManager<ApplicationUser> _userManager;
    public ApplicationClaimsIdentityFactory(UserManager<ApplicationUser> userManager, 
        IOptions<IdentityOptions> optionsAccessor):base(userManager, optionsAccessor)
    {}
    public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
    {
        var principal = await base.CreateAsync(user);
        if (user.IsDeveloper)
        {
            ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
                new Claim("IsDeveloper", "true")
            });
        }
        return principal;
    }
}

then you need to register it in Startup.ConfigureServices:

services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, ApplicationClaimsIdentityFactory>();

2) Check the claim

Custom policy

In Startup.ConfigureServices:

services.AddAuthorization(options =>
{
    options.AddPolicy("Developer", policy =>
                        policy.RequireClaim("IsDeveloper", "true"));
});

and protect your action for developers:

[Authorize(Policy = "Developer"), HttpGet]
public string DeveloperSecret()
{
    return "Hello Developer"
}

Check the claim manually

Somewhere in the controller:

bool isDeveloper = User.Claims.Any(c => c.Type == "IsDeveloper" && c.Value == "true")

If you are using some other authentication the idea should be the same.

like image 124
AlbertK Avatar answered Oct 13 '22 00:10

AlbertK