title: Only validate JWT if bearer header is present
body: <p>I have a few API endpoints (.net core mvc) that will use the logged-in user (JWT) if the user is logged in, but anyone is allowed to call the method.
  By using <code>[AllowAnonymous]</code> together with <code>[Authorize]</code> I get the functionality I'm looking for but if the sent JWT is expired, I'm not getting a 401, but instead it is treated as an anonymous request.</p>
  <p>I need the authorization logic to treat the endpoint as it was <code>[Authorize]</code> only if there is a Authorization: Bearer header, meaning that if the token is expired, it should return a 401</p>
  <p>This functionality is only needed on a few endpoints and not on a full controller</p>
  <p>I've tried the combination of <code>[AllowAnonymous]</code> + <code>[Authorize]</code>.</p>
  <p>Also tried <code>RequireAssertion</code> when creating the policy, but doesn't seem to have been meant for this</p>
  <p>The method I'm using for testing:</p>
  <pre><code>[HttpPost]
  [Route(&quot;testToken&quot;)]
  [AllowAnonymous]
  [Authorize(Policy = AuthFilterConvension.POLICY_AUTHORIZE_WHEN_HAS_BEARER)]
  public async Task&lt;IActionResult&gt; testToken()
  {
      var user = await _signInManager.UserManager.GetUserAsync(HttpContext.User);
          return Ok(new {result = user});
      }
  </code></pre>
  <p>Setting up auth to support both cookies + JWT:</p>
  <pre><code>services.AddAuthorization(o =&gt;
              {
                  o.AddPolicy(AuthFilterConvension.POLICY_AUTHORIZE_WHEN_HAS_BEARER, b =&gt;
                  {
                      b.RequireRole(&quot;Admin&quot;);
                      b.RequireAuthenticatedUser();
                      b.AuthenticationSchemes = new List&lt;string&gt; {JwtBearerDefaults.AuthenticationScheme};
                      
                  });
              });
              services.AddAuthentication()
                  .AddCookie()
                  .AddJwtBearer(cfg =&gt;
                      {
                          var issuer = Environment.GetEnvironmentVariable(&quot;JWT_ISSUER&quot;);
                          var tokenKey = Environment.GetEnvironmentVariable(&quot;JWT_TOKEN_KEY&quot;);
  
                          cfg.RequireHttpsMetadata = false;
                          cfg.SaveToken = true;
  
                          cfg.TokenValidationParameters = new TokenValidationParameters
                          {
                              RequireExpirationTime = true,
                              RequireSignedTokens = true,
                              ValidateAudience = true,
                              ValidateIssuer = true,
                              ValidateLifetime = true,
  
                              ValidIssuer = issuer,
                              ValidAudience = issuer,
                              IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenKey))
                          };
                      }
                  );
  </code></pre>
  <p>I would expect the <code>[Authorize]</code> header to return 401 Unauthorized when using expired tokens instead of calling the method as anonymous. Is this possible to set up?</p>
  <p><strong>Update</strong>
  I created the attribute like this:</p>
  <pre><code>public class AuthorizeBearerWhenPresent : ActionFilterAttribute, IAsyncAuthorizationFilter
      {
          public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
          {
              var headers = context.HttpContext.Request;
              
              //TODO: Test header
              var httpContext = context.HttpContext;
              var authService = httpContext.RequestServices.GetRequiredService&lt;IAuthorizationService&gt;();
  
              var authResult = await authService.AuthorizeAsync(httpContext.User, context,
                  AuthFilterConvension.POLICY_AUTHORIZE_WHEN_HAS_BEARER);
              
              if (!authResult.Succeeded)
              {
                  context.Result = new UnauthorizedResult();
              }
          }
      }
  </code></pre>
  <p>However, no matter what I'm sending to the <code>authService</code> it returns true. Doesn't matter if I send an invalid JWT header or no header. Shouldn't this be the correct way to get executed a policy?</p>