Friday, August 2, 2019

Dynamic Authorization Policies in .NetCore Identity Framework


When it comes to implementing an Authorization Engine or Permission Engine for an ASP.Net Core Web API, we can use the Identity Framework.  Please refer my previous post on Claim based Authorization in Asp.Net Core.
If you have a basic understanding on how claim based authorization works, you should be already familiar with security policies. Security Policies are used to decorate controller action to control authorization, and the policy defines what is required to satisfy the policy. Usually a Policy check if the logged in user has certain claims (one or multiple) with him. Normally one or few claims required to satisfy a policy and most of the time it is one claim per policy.  
If your authorization engine is mainly based on one claim per policy (or if you can model it in such away), you will notice that you will have to write large amount of security policies where each policy is checking whether the user has a certain claim. This is a repetitive and annoying task which you would have to spend considerable amount of time.

What if Possible to Decorate Controller Actions with Claim Itself?


That’s sounds nice. Instead of writing hundreds of security policies, just decorate the actions with the claim that required to access it. But unfortunately it is not supported by Identity Framework by default. It only allows to specify the policy names or the role names.

Is There a Workaround?


Yes! Identity framework supports creating dynamic policies by implementing IAuthorizationPolicyProvider and AuthorizeAttribute

Custom Authorize Attribute

internal class ClaimAuthorizeAttribute : AuthorizeAttribute
{
    const string POLICY_PREFIX = "REQUIRE_CLAIM_";

    public ClaimAuthorizeAttribute(string claim) => Claim = claim;

    public string Claim
    {
        get
        {
            var claim = Policy.Substring(POLICY_PREFIX.Length);
            return claim;
        }
        set
        {
            Policy = $"{POLICY_PREFIX}{value}";
        }
    }
}

Custom Authorization Policy Provider


internal class CustomAuthorizationPolicyProvider : IAuthorizationPolicyProvider
{
    const string POLICY_PREFIX = "REQUIRE_CLAIM_";

    public Task GetDefaultPolicyAsync()
    {
               return Task.FromResult(new AuthorizationPolicyBuilder()
                       .RequireAuthenticatedUser().Build());
    }

    public Task GetPolicyAsync(string policyName)
    {
       var requiredClaim = policyName.Substring(POLICY_PREFIX.Length);

       var policy = new AuthorizationPolicyBuilder();

       policy.RequireClaim(CustomClaimTypes.Permission, requiredClaim);

       return Task.FromResult(policy.Build());
         }
 }

Tell .Net Core to Use Our Custom Policy Provider Instead the Default One


In the startup.cs add the following line in ConfigureServices() Method.
services.AddSingleton();

Decorating Controller Action with the New Attribute


[ClaimAuthorize(“DRIVER_VIEW”)]
public async Task GetAsync(string id)
{
    var result = await _driverService.GetDriverWithPostCodesAsync(id);
    return result;
}

Summary


Using this approach you can simply outsource the burden of creating hundreds of authorization policies. Eventually that will save large amount of development time of your team. Also the code will be nice and clean.

No comments:

Post a Comment