Reputation: 82341
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?
Upvotes: 2
Views: 953
Reputation: 10035
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;
}
Upvotes: 1