2

I have two JWTs that are included in all the calls to my service. The first one (called UserJwt) is the one that I want to be used for [Authorize] for most service operations. The second one (called ApplicationJwt) has useful information that I would also like to be in the User.Identities list of ClaimsIdentity objects.

I setup my code so that the UserJwt is always used and the ApplicationJwt is ignored:

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        // Setup the JWT stuff here for the UserJwt         
    })

This works fine, but but I want both JWTs parsed and put into the User.Identities list.

I tried setting up my code to follow this answer, (to the question: Use multiple JWT Bearer Authentication) but this allows either one (UserJwt or ApplicationJwt).

At worst I need it to require both. However, I prefer it to only require UserJwt but include ApplicationJwt as a ClaimsIdentity if found.

    services.AddAuthentication()
        .AddJwtBearer("UserJwt", options =>
        {
            // Setup the JWT stuff here for the UserJwt
        })
        .AddJwtBearer("ApplicationJwt", options =>
         {
             // Setup the JWT stuff here for the ApplicationJwt
         });

    services.AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("UserJwt", "ApplicationJwt")
            .Build();
    });

How can I get both JWTs to be in the User.Identities list, have the UserJwt be the one that is used for [Authorize], but also allow [Authorize(Policy = "ApplicationJwt")] on some service operations?

Vaccano
  • 78,325
  • 149
  • 468
  • 850
  • 1
    Does this answer your question? [Use multiple JWT Bearer Authentication](https://stackoverflow.com/questions/49694383/use-multiple-jwt-bearer-authentication) – Mosia Thabo Apr 23 '20 at 22:28
  • Why not combine JWTs in a single one and populating claims in multiple "User.Identities"? – Hadi Samadzad Apr 23 '20 at 22:30
  • 1
    @MosiaThabo - No it does not answer my question. (I linked to that answer in my question. I said that I tried it and it did not work. (My second set of example code is how I tried to make that answer work.)) – Vaccano Apr 23 '20 at 22:35
  • @Hadi - The JWT's come in from separate headers. Is there a "merge" JWTs feature in .Net Core? – Vaccano Apr 23 '20 at 22:36
  • I don't know any built-in feature for that. but another approach would be using middleware to handle "ApplicationJwt" separately from UseAuthentication middleware. So, you add application Jwt claims before or after authentication by yourself. – Hadi Samadzad Apr 23 '20 at 22:49
  • *The JWT's come in from separate headers.* Are you saying they are from different http headers on the same request? – weichch Apr 24 '20 at 04:58
  • @Weichch - Yes. One is put in the request by the calling application, and the other is put in by my API Gateway. Both are on the same request and have separate values in separate header keys. – Vaccano Apr 24 '20 at 17:38

1 Answers1

1

One option here is adding custom requirements to default policy.

Assume UserJwt contains specific claims:

options.DefaultPolicy = new AuthorizationPolicyBuilder()
    .AddAuthenticationSchemes("UserJwt", "ApplicationJwt")
    .RequireAuthenticatedUser()
    .AddRequirements(
        // Assume UserJwt contains a AuthenticationMethod claim where 
        // value is equal to User
        new ClaimsAuthorizationRequirement(
            ClaimTypes.AuthenticationMethod, new[] { "User" }
        )
    )
    .Build();

Also see other built-in requirement types.

Note that when requirement is not met, user is still authenticated but denied access. To handle forbidden scenario, use JwtBearerEvents.OnForbidden event:

OnForbidden = async context =>
{
    context.Response.StatusCode = 401;
}
weichch
  • 9,306
  • 1
  • 13
  • 25