In ASP.NET Core 6.0 project, I have a requirement to authenticate the request if the authorization bearer token satisfies any of the authentication schema say "jwt1" or "jwt2".

The authorization policy also differ based on the authentication schema that was applied to authenticate the request. This is because the claim to validate vary based on the authentication schema that was applied to authenticate the request.

If the request is authenticated via schema say "jwt1" then I want to apply the authorization policy "jwt1_policy"

[Authorize(Policy="jwt1_policy")]
[Route("weather"), HttpGet]

If the request is authenticated via schema say "jwt2" then I want to apply the authorization policy "jwt2_policy" instead of "jwt1_policy" on the same endpoint.

[Authorize(Policy="jwt2_policy")]
[Route("weather"), HttpGet]

I want to apply either "jwt1_policy" or "jwt2_policy" on the same endpoint depending on the authentication schema that was applied to authenticate the request.

As I understand from the document, if I add multiple authorization attributes in the same endpoint then both policies will be checked.

[Authorize(Policy="jwt1_policy")]
[Authorize(Policy="jwt2_policy")]
[Route("weather"), HttpGet]

Please let me know if anyone has idea of how to choose different authorization policy based on the authentication schema on the same endpoint.

I also have a related question on the RequiredScope attribute. Is it possible to apply the RequiredScope only if a particular authentication schema was applied. We want to apply the RequiredScope only if authentication schema jwt1 was applied to authenticate the request. Is that possible to achieve? Is it possible to implement custom version of RequiredScope attribute so that we can skip the RequiredScope check if a different authentication schema was applied to authenticate the request?

[Authorize]
[RequiredScope("read")
[Route("weather"), HttpGet]
2

There are 2 best solutions below

4
Qiang Fu On

You could create 3 policy to allow either of the scheme. For example

//Add a policy called "Jwt_Or_Cookie" to allow either jwt or cookie.
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("Jwt_Or_Cookie", policy =>
    {
        policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
        policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme);
        policy.RequireAuthenticatedUser();

    });
    options.AddPolicy("Only_Jwt", policy =>
    {
        policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
        policy.RequireAuthenticatedUser();

    });
    options.AddPolicy("Only_Cookie", policy =>
    {
        policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme);
        policy.RequireAuthenticatedUser();

    });
});

Then [Authorize(Policy = "Jwt_Or_Cookie")] will work for either authentication.
[Authorize(Policy = "Only_Jwt")] will only allow jwt authentication.
[Authorize(Policy = Only_Cookie")] will only allow cookie authentication.

0
Shaheer On

The claims that we need to validate as part of authorization differ based on the authentication schema was applied to successfully to validate the token.

If the token was successfully validated using schema "jwt1" then we need to verify that token contain the required scope claim and different endpoint has different scope requirements.

If the token was successfully validated using schema "jwt2" then we need to verify that token contain the required role claim and different endpoint has different role requirements.

var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder("jwt1", "jwt2");
defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();

var jwt1ReadWeatherAuthPolicyBuilder = new AuthorizationPolicyBuilder("jwt1");
options.AddPolicy("jwt1_read_weather_policy", jwt1ReadWeatherAuthPolicyBuilder
    .RequireClaim("scope", "read_weather")
    .RequireAuthenticatedUser()
    .Build());

var jwt2ReadWeatherAuthPolicyBuilder = new AuthorizationPolicyBuilder("jwt2");
options.AddPolicy("jwt2_read_weather_policy", jwt2ReadWeatherAuthPolicyBuilder
    .RequireRole("read_weather")
    .RequireAuthenticatedUser()
    .Build());

Now I want to apply both policies "jwt1_read_weather_policy" and "jwt2_read_weather_policy" on the same endpoint, but at the same time policy should be checked based on the authentication schema that was applied to validate the token successfully.

User can pass either of the token (jwt1 or jwt2) to the same endpoint. If jwt1 is used then we need to validate the scope claim. If jwt2 is used then we need to the role claims. I hope the requirement is clear now. Please share if this is possible to achieve in the standard way without need of building custom authentication middleware.