title: Custom JWT Token Authorisation in MVC Core Web API
body: <p>I have been implementing my own JWT Token <code>Authentication/Authorisation</code>, without using Identity etc.</p>
  
  <p>Based on these links I have successfully created a JWT Token - and implemented the Authorisation using the Attribute <code>[Authorize]</code></p>
  
  <p><a href="https://stormpath.com/blog/token-authentication-asp-net-core" rel="nofollow">Token Authentication 1</a></p>
  
  <p><a href="https://goblincoding.com/2016/07/03/issuing-and-authenticating-jwt-tokens-in-asp-net-core-webapi-part-i/" rel="nofollow">Token Authentication 2</a> - [My Code is exactly the same as this]</p>
  
  <p>The problem I am having is that in the application I am working on, the Authorisation is based on <code>FEATURE</code> not <code>ROLE</code>.</p>
  
  <p>This is the DB Schema</p>
  
  <pre><code>1. User
  -------------------
     UserId (PK)
  
  2. Role 
  -------------------
     RoleId (PK)
  
  
  3. RoleFeatures
  -------------------
     (RoleId PK, FK)
     (FeatureId PK, FK)
  
  4. Features
  -------------------
     FeatureId (PK)
  </code></pre>
  
  <p>The Roles are NOT pre-defined but Features are pre-defined e.g. Create User, Update User</p>
  
  <p>Let's say we have 2 Roles <code>"User Manager"</code> and <code>"User and Customer Admin"</code> - The users from both these roles can <code>Create, Update and Delete</code> Users.</p>
  
  <p>Now in the Application Controller instead of doing </p>
  
  <pre><code>   [Authorise(Roles="User Manager, User and Customer Admin")]
     public IActionResult CreateUser()
  </code></pre>
  
  <p>I need this:</p>
  
  <pre><code>   [Authorise(Features="Create User")]
     public IActionResult CreateUser()
  </code></pre>
  
  <p>How do I come about implementing this type of JWT Token Authorization in MVC Core Web API? </p>
  
  <p>One way to do it would be to save the Features in the JWT Token as a Claim - but the problem with that is that a Role can have say 20 features, and saving them in the Token will increase the Token Size dramatically -</p>
  
  <p>So what I need is a Custom Implementation of the Authorize Attribute which get's the userId from the JWT Token (userId is Claim in JWT Token), then get's the Role Features from the DB based on UserId and apply's the Authorization.</p>
  
  <h2>EDIT</h2>
  
  <p>Based on the .NET Core Documentation - I found that I we can create a Policy</p>
  
  <p><a href="https://docs.asp.net/en/latest/security/authorization/policies.html" rel="nofollow">https://docs.asp.net/en/latest/security/authorization/policies.html</a></p>
  
  <p>So I went ahead and created a Requirement and a Requirement Handler as follows:</p>
  
  <pre><code>public class FeatureRequirement : IAuthorizationRequirement
  {
      public string FeatureName { get; set; }
  
      public FeatureRequirement(string featureName) { FeatureName = featureName; }
  }
  
  public class FeatureRequirementHandler : AuthorizationHandler&lt;FeatureRequirement&gt;
  {
      protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FeatureRequirement requirement)
      {
          var userId = context.User.Claims.FirstOrDefault(s =&gt; s.Type == "UserId");
  
          if (userId == null) { return Task.FromResult(0); }
  
          //TODO: Get User Features from DB based on UserId
          var userFeatures = new List&lt;string&gt; { "Create User", "Update User" };
  
          if (userFeatures.Contains(requirement.FeatureName))
          {
              context.Succeed(requirement);
          }
          return Task.FromResult(0);
      }
  }
  </code></pre>
  
  <p>and in the Startup.cs</p>
  
  <pre><code>  services.AddAuthorization(options =&gt;
       {
        // Create the Policies
        // Problem here have to define a policy for each feature 
  
         options.AddPolicy("Create User", policy =&gt; policy.Requirements.Add(new FeatureRequirement("Create User")));
  
         options.AddPolicy("Update User", policy =&gt; policy.Requirements.Add(new FeatureRequirement("Update User")));
  
       });
  
      services.AddScoped&lt;IAuthorizationHandler, FeatureRequirementHandler&gt;();
  </code></pre>
  
  <p>and then in the Controller:</p>
  
  <pre><code>   [Authorise(Policy="Create User")]
     public IActionResult CreateUser()
  
     // AND
  
     [Authorise(Policy="Update User")]
     public IActionResult UpdateUser()
  </code></pre>
  
  <p>Which is working as expected (returns 403 if feature is not assigned to user)</p>
  
  <p>The Problem with this is that I have to create a new Policy for each and every single Feature - is there a better way to do this?</p>