Authorization with JWT
The Arcus.WebApi.Security
package provides a mechanism that uses JWT (JSON Web Tokens) to authorize requests access to the web application.
This authorization process consists of the following parts:
- Find the OpenID server endpoint to request the correct access token
- Determine the request header name you want to use where the access token should be available
Globally enforce JWT authorization
Installation
This feature requires to install our NuGet package:
PM > Install-Package Arcus.WebApi.Security
Usage
The JwtTokenAuthorizationFilter
can be added to the request filters in an ASP.NET Core application.
This filter will then add authorization to all endpoints via the configured properties on the filter itself.
Example:
using Arcus.WebApi.Security.Authorization.Jwt;
using Microsoft.AspNetCore.Builder;
using Microsoft.IdentityModel.Tokens;
WebApplicationBuilder builder = WebApplication.CreateBuilder();
builder.Services.AddControllers(mvcOptions =>
{
// Default configuration:
// By default, the JWT authorization filter will use the Microsoft 'https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration' OpenID endpoint to request the configuration.
mvcOptions.AddJwtTokenAuthorizationFilter();
mvcOptions.AddJwtTokenAuthorizationFilter(options =>
{
// Default configuration with validation parameters:
// One can still use the default Microsoft OpenID endpoint and provide additional validation parameters to manipulate how the JWT token should be validated.
var parameters = new TokenValidationParameters();
options.JwtTokenReader = new JwtTokenReader(parameters);
// Default configuration with application ID:
// One can use the Microsoft OpenID endpoint and provide just the application ID as input for the validation parameters.
// By default will only the issuer singing keys and lifetime be validated.
string applicationId = "e98s9-sadf8981-asd8f79-ahtew8";
options.JwtTokenReader = new JwtTokenReader(applicationId);
// Custom OpenID endpoint:
// You can use your own custom OpenID endpoint by providing another the endpoint in the options; additionally with custom validation parameters how the JWT token should be validated.
var parameters = new TokenValidationParameters();
string endpoint = "https://localhost:5000/.well-known/openid-configuration";
options.JwtTokenReader = new JwtTokenReader(parameters, endpoint);
// Emitting security events:
// One can opt-in for security events during the authorization of the request (default: `false`).
options.EmitSecurityEvents = true;
});
});
Custom Claim validation
It allows validating not only on the audience claim in the JWT token, but any type of custom claim that needs to be verified
using Microsoft.AspNetCore.Builder;
using Microsoft.IdentityModel.Tokens;
WebApplicationBuilder builder = WebApplication.CreateBuilder();
builder.Services.AddControllers(mvcOptions =>
{
// Default configuration with issuer:
// One can use the Microsoft OpenID endpoint and provide just the issuer as input for the validation parameters.
var claimCheck = new Dictionary<string, string>
{
{"aud", Issuer}
};
mvcOptions.AddJwtTokenAuthorizationFilter(claimCheck);
// Custom OpenID endpoint:
// You can use your own custom OpenID endpoint by providing another the endpoint in the options; additionally with custom validation parameters and custom claims to manipulate how the JWT token should be validated.
var claimCheck = new Dictionary<string, string>
{
{"aud", Issuer},
{"oid", "fa323e12-e4b8-4e22-bb2a-b18cb4b76301"}
};
mvcOptions.AddJwtTokenAuthorizationFilter(claimCheck);
// Default configuration with validation parameters:
// One can still use the default Microsoft OpenID endpoint and provide additional validation parameters and custom claims to manipulate how the JWT token should be validated.
var parameters = new TokenValidationParameters();
var claimCheck = new Dictionary<string, string>
{
{"aud", Issuer},
{"oid", "fa323e12-e4b8-4e22-bb2a-b18cb4b76301"}
};
mvcOptions.AddJwtTokenAuthorizationFilter(claimCheck);
}});
Bypassing authentication
The package supports a way to bypass the JWT authorization for certain endpoints. This works with adding one of these attributes to the respectively endpoint:
BypassJwtAuthorization
AllowAnonymous
Works on both method and controller level.
using Arcus.WebApi.Security.Authorization.Jwt;
[ApiController]
public class SystemController : ControllerBase
{
[HttpGet('api/v1/health')]
[BypassJwtAuthorization]
public IActionResult GetHealth()
{
return Ok();
}
}
Accessing secret store on JWT Bearer token authentication
This package also provides an extra extension to access the Arcus secret store while configuring JWT Bearer token authentication. Access to the secret store will help to provide, for example, issuer symmetric keys.
using Arcus.Security.Core;
using Microsoft.AspNetCore.Builder;
WebApplicationBuilder builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication(...)
.AddJwtBearer((options, serviceProvider) =>
{
var secretProvider = serviceProvider.GetRequiredService<ISecretProvider>();
string key = secretProvider.GetRawSecretAsync("JwtSigningKey").GetAwaiter().GetResult();
options.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
};
});