简体   繁体   中英

Claims-based authorization and where to add what the user can do

I just implemented a web api using claims-based authorization. A user can login in the system and a set of claims are pulled from the database and added to the httpContext.User.Identity depending on what the user can do.

After registering the policies in Startup.cs with something like:

services.AddAuthorization(options =>
{
    options.AddPolicy(PoliciesDefinitions.RequiresVehicleList, policy => policy.RequireClaim(Permissions.VehiclesList.ToString()));

    ...               
});

I can use the Authorize attribute on the controllers method that I want to authorize with something like:

Authorize(Policy=PoliciesDefinitions.RequiresDriversList)]
[HttpGet]
public ActionResult Get() { ... }

This works ok but today I was reading microsoft documentation a bit more thoroughly and I came across this statement in the Claims-based authorization documentation:

A claim is a name value pair that represents what the subject is, not what the subject can do

At this time I'm doing exactly what microsfot suggests not to do. I'm adding what the user can do (permissions) to the identity. So, this leads me to think, am I doing it wrong? If the answer is yes, where would you store the user permissions and how would authorization work?

This allows for the KVP, and multiple values.

// with Razor, you did not specific if it was core 2, 3.1 or Razor

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Vendors", policy =>
                          policy.RequireClaim("Type.Tykt.org", "Dealer", "Driver", "WholeSaler", "Asset", "Repair"));
    });
}

Option 2:

Also there is a claims collection, you can add it after user successfully logs in.

var user = new User {
  Email = "xyz@tykt.org",
  Name =  "xyz"
}

user.Claims.Add(new IdentityUserClaim<string> 
{ 
    ClaimType="your-type",   // your key
    ClaimValue="your-value"  // your value
});

await userManager.CreateAsync(user);

Update Ref MSDN :

Its really your choice on how you store retrieve, if I'm understanding the question, your question specifically around is the value of the claim.

Typically, the mapping and verification happens in something like a PermissionHandler: IAuthorizationHandler or a generic approach MinimumAgeHandler: AuthorizationHandler<MinimumAgeRequirement> . Which, loads the values, and handles the requirement verification of a specific permission for eg min age, but the actual claims (what are you stating/ min age policy vs the value is usually in the DB, like DOB= 1/1/1990 ) travel with the Principal object. Now, where you choose to retrieve the value of the claim is upto you

In the below function he is getting value for the Key from the Context and then validating

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   MinimumAgeRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
                                        c.Issuer == "http://contoso.com"))
        {
            return Task.CompletedTask;
        }

        var dateOfBirth = Convert.ToDateTime(
            // He gets the value on the server-side from any store or 3rd party relayer
            context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth && 
                                        c.Issuer == "http://contoso.com").Value);

        int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
        if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
        {
            calculatedAge--;
        }

        if (calculatedAge >= requirement.MinimumAge)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM