title: Authorize Policy always return 403 (Forbidden) - MVC/API
body: <p>I created an API (.Net Core 2 with EF Core) with an endpoint to retrieve certain roles. I integrated ASPNetIdentity into my project and I am using AspNetRoles and the AspNetRoleClaims. </p>
  
  <p>When calling the API the user has a specific role (Admin) in my case. This role has a few role claims. In the startup.cs I added policies for this role:</p>
  
  <pre><code>   options.AddPolicy(
        "Create Roles", policy =&gt; policy.RequireClaim("Can create roles", "role.create"));
     options.AddPolicy(
        "View Roles", policy =&gt; policy.RequireClaim("Can read roles", "role.read"));
     options.AddPolicy(
        "Edit Roles", policy =&gt; policy.RequireClaim("Can update roles", "role.update"));
     options.AddPolicy(
        "Delete Roles", policy =&gt; policy.RequireClaim("Can delete roles", "role.delete"));
  </code></pre>
  
  <p>In my Frontend the users can login with their Microsoft (azure) account and their oidc claim (ID) matches the ID in the AspNetUser table, if their oidc is not found in the user table, they are automatically added (with their oidc id as the aspnetuser id) and they get a default role.</p>
  
  <p>When calling the Role endpoint however, it always returns a 403 error (forbidden). When I check the tables, the user has the right role and role claims to access the endpoint. How is it possible that it keeps returning 403? </p>
  
  <p>The endpoint looks as follow:</p>
  
  <pre><code>[HttpGet]
  [Authorize(Policy = "View Roles")]
  public IEnumerable&lt;IdentityRole&gt; GetRole()
  {
       return _context.Roles;
  }
  </code></pre>
  
  <p>After some research I found a post which tells that you need to include the role (claim) of the user in the token which is being send to the API, though this would mean I will need a GET endpoint that first returns the role(s) of the user, the frontend needs to pick it up and add it to the token, and then call all the other endpoints with the role included in the token? Or am I on the wrong track here? </p>
  
  <p><strong>----UPDATE----</strong></p>
  
  <p>I am 90% sure that the Policy/Authorization check needs the Role claim to be included in Token of the user. The process however is as following right now:</p>
  
  <ol>
  <li>The user goes to the frontend project (react frontend).</li>
  <li>The frontend uses adal.js to check if the user is authenticated, if he is not authenticated, then the user gets redirected to the Microsoft login page. </li>
  <li>After successful logging in, the API is being called.</li>
  <li>In the DI (AddJwtBearer) of the API, the oid claim is being compared with the ID of the ASpNetUsers table, if it is not present, the user is added to the AspNetUser table using the oid value for the ID of the AspNetUser. </li>
  </ol>
  
  <p>Now that the user is also added in the AspNetUser table, I can use the Asp.Net Identity for doing Authorization using Roles and RoleClaims. </p>
  
  <p>The problem however is that the initial received token by the API is the Azure token, which knows nothing about my Identity tables (correct me if I am wrong). I believe this is also the cause of my policy not working (again, correct me if I am wrong).</p>
  
  <p>I found a post where the problem is more or less the same (<a href="https://joonasw.net/view/adding-custom-claims-aspnet-core-2" rel="noreferrer">https://joonasw.net/view/adding-custom-claims-aspnet-core-2</a>), the trick is to extend the current token with my needed Identity claims such as  <code>ClaimTypes.Role</code>. </p>
  
  <p>My code to achieve this is as follow:</p>
  
  <pre><code>// Add authentication (Azure AD)
              services
                  .AddAuthentication(sharedOptions =&gt;
                  {
                      sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                      sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 
                      sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // Use JWT as ChallendgeSchema, if not, ASPNet Identity will be used by default and this will return a default non-existing endpoint (because it is not created): Account/Login; https://stackoverflow.com/questions/45878166/asp-net-core-2-0-disable-automatic-challenge
                  })
                  .AddJwtBearer(options =&gt;
                  {
                      options.Audience = this.Configuration["AzureAd:ClientId"];
                      options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";
  
                      // Added events which checks if the user (token user) exists in our own database, if not then the user is being added with a 'User' role
                      options.Events = new JwtBearerEvents()
                      {
                          OnTokenValidated = context =&gt;
                          {
                              // Check if roles are present
                              CheckRoles cr = new CheckRoles();
                              cr.CreateRoles(services.BuildServiceProvider());
  
                              // Check if the user has an OID claim(oid = object id = user id)
                              if (!context.Principal.HasClaim(c =&gt; c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier")) 
                              {
                                  context.Fail($"The claim 'oid' is not present in the token.");
                              }
  
                              ClaimsPrincipal userPrincipal = context.Principal;
  
                              CheckUser cu = new CheckUser();
  
                              cu.CreateUser(userPrincipal, services.BuildServiceProvider());
  
                              // Extend the current token with my (test) Role claim
                              var claims = new List&lt;Claim&gt;
                              {
                                  new Claim(ClaimTypes.Role, "Admin")
                              };
                              var appIdentity = new ClaimsIdentity(claims);
                              context.Principal.AddIdentity(appIdentity);
  
  
                              return Task.CompletedTask;
                          }
                      };
                  });
  </code></pre>
  
  <p>Sadly the above does not work, when calling the API from the frontend, the token remains unchanged and the RoleClaim is not being added.. Anyone has a clue how to add my RoleClaim to the token so that I can use my policies? </p>