I have an ASP.NET Core application which uses the following piece of logic to configure Authentication / Authorization.
services.AddAuthorization(
static options => options.AddPolicy(
"Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build()));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.Authority = identityProviderEndpoint;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = identityProviderEndpoint,
ValidAudience = applicationAudience,
RequireSignedTokens = true,
};
});
Now, this works, when example, validating a token from Auth0. For testing purposes, I want to use custom options (disabling all checks, since it's not important when testing).
Here's a test case I have created with custom options.
[Fact(DisplayName = "HTTP Forbidden: Requesting (Valid JWT) an authorized endpoint (JWT Validation disabled).")]
internal async void RequestingAnEndpointThatRequiresAuthorizationWithAValidJWT()
{
// ARRANGE.
HttpClient httpClient = this.webApplicationFactory.WithWebHostBuilder(
builder =>
{
builder.ConfigureTestServices(
services =>
{
var options = new JwtBearerOptions();
options.TokenValidationParameters = new TokenValidationParameters
{
#pragma warning disable CA5404 // "Do not disable token validation checks" - By design. ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false, #pragma warning restore CA5404 ValidateIssuerSigningKey = false, RequireSignedTokens = false, IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes("UTrust.S1gn1ngK3Y!")), };
services.AddSingleton(options);
});
})
.CreateClient();
httpClient.DefaultRequestHeaders.Add(
"Authorization",
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.T7sFpO0XoaJ9JWsu2J1ormK99zs4zIr2s25jjl8RVSw");
// ACT.
HttpResponseMessage result = await httpClient.GetAsync("/authorized")
.ConfigureAwait(false);
// ASSERT.
result.Should()
.HaveStatusCode(HttpStatusCode.OK);
}
I'm passing a JWT which can be validated on https://jwt.io/. The test fails however with an Unauthorized HTTP Status code.
If inside the application, I change the options with the options I'm using in the test, the same token is considered value and I get an HTTP Ok status code.
This is validated using the following cURL request.
curl http://localhost:5160/authorized -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.T7sFpO0XoaJ9JWsu2J1ormK99zs4zIr2s25jjl8RVSw" -v
What am I missing here? Why is the token considered invalid in the test context, but valid in the actual application (if I use the same options in both)?
CodePudding user response:
You registering JwtBearerOptions
directly in IoC container, so it doesn't picked up by configuration system.
You need to change code to something like this:
services.Configure(JwtBearerDefaults.AuthenticationScheme, options => {
// ...
});