title: OpenIdConnect access_token size and accessing claims server side
body: <p>I am trying to wrap my head around several concepts here but I don't want this question to be too broad - basically what we are trying to do is use role claims as permissions to lock down our API but I am finding that the access_token is becoming too big.  </p>
  
  <p>We are using OpenIddict and ASP.NET Identity 3 on the server side.  We have implemented the default AspNetRoleClaims table to store our claims for each role - using them as permissions.</p>
  
  <p>We lock down our API endpoints using custom policy based claims authorization as shown here:</p>
  
  <p><a href="https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies" rel="nofollow noreferrer">Custom Policy Based Authorization</a></p>
  
  <p>The main issue I am finding is that our access_token containing our claims is becoming very large. We are attempting to make the ClaimType and Value to be very small in the database to make the claims footprint smaller.  We have a basic CRUD type permission scheme, so for each "module" or screen in our SPA client app, there are 4 permissions.  The more modules we add to our application, the more the claims are growing in the access_token and our Authorization Bearer header is becoming very large.  I am worried about this becoming not very scalable as the app grows.</p>
  
  <p>So the claims are embedded in the access_token and when I hit my endpoint that is locked down with a custom Policy like this...</p>
  
  <pre><code>[Authorize(Policy="MyModuleCanRead")]
  [HttpGet]
  public IEnumerable&lt;MyViewModel&gt; Get()
  </code></pre>
  
  <p>I can then access my ASP.NET Identity User and User.Claims in the AuthorizationHandler.</p>
  
  <p>Sorry in advance if this is an obvious question - but I am wondering - in order to get the Custom Policy Based Authorization to work - does it absolutely require the claims to be in either the id_token or the access_token in order to call the handler?</p>
  
  <p>If I remove the claims from the access_token, then my AuthorizationHandler code does not get hit and I cannot access my endpoint that is locked down with my custom Policy.</p>
  
  <p>I am wondering if it is possible to use a custom claims policy but have the actual code that checks for the Claims inside the Authorization handler, so that the claims are not passed with each HTTP request, but are fetched server side from the Authorization cookie or from the database.</p>
  
  <p><strong>* UPDATE *</strong></p>
  
  <p>Pintpoint's answer using Authorization handlers along with the comment on how to remove additional role claims from the cookie achieved just what I was looking for. </p>
  
  <p>In case this helps anyone else - here is the code to override the UserClaimsPrincipalFactory and prevent the role claims from being written to the cookie.  (I had many role claims as permissions and the cookie(s) and request headers were becoming too large)</p>
  
  <pre><code>public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory&lt;ApplicationUser, IdentityRole&gt;
  {
      public AppClaimsPrincipalFactory(UserManager&lt;ApplicationUser&gt; userManager, RoleManager&lt;IdentityRole&gt; roleManager, IOptions&lt;IdentityOptions&gt; optionsAccessor) : base(userManager, roleManager, optionsAccessor)
      {
      }
      public override async Task&lt;ClaimsPrincipal&gt; CreateAsync(ApplicationUser user)
      {
          if (user == null)
          {
              throw new ArgumentNullException(nameof(user));
          }
          var userId = await UserManager.GetUserIdAsync(user);
          var userName = await UserManager.GetUserNameAsync(user);
          var id = new ClaimsIdentity(Options.Cookies.ApplicationCookieAuthenticationScheme,
              Options.ClaimsIdentity.UserNameClaimType,
              Options.ClaimsIdentity.RoleClaimType);
          id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
          id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName));
          if (UserManager.SupportsUserSecurityStamp)
          {
              id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
                  await UserManager.GetSecurityStampAsync(user)));
          }
  
          // code removed that adds the role claims 
  
          if (UserManager.SupportsUserClaim)
          {
              id.AddClaims(await UserManager.GetClaimsAsync(user));
          }
          return new ClaimsPrincipal(id);
      }
  }
  </code></pre>