Open Jogai opened 6 months ago
Hello @Jogai,
Could you provide more insights into your specific use case or objective?
Security.Jwt is designed for generating JWTs (jws, jwe) using a public key cryptosystem. In other hand Security.JwtExtensions was designed to validate jwt issued by third-party systems, leveraging the jwks uri for this purpose.
Security.Jwt
package also includes its extensions for validating tokens it has generated itself.
In the code snippet you've shared, I noticed the usage of both Security.Jwt
and Security.JwtExtensions
:
builder.Services.AddJwksManager()
.UseJwtValidation(); // <-- Security.Jwt
options.SetJwksOptions(
new JwkOptions // <-- Security.JwtExtensions
{
Audience = "audience", Issuer = "https://keycloak.myProduct.eu/realms/myProduct",
JwksUri = "https://keycloak.myProduct.eu/realms/myProduct/protocol/openid-connect/certs",
KeepFor = TimeSpan.FromHours(1)
});
From my experience, integrating both of these components into the same project can lead to unexpected behaviors. This is because they alter the JWT validation process in different ways, potentially causing compatibility issues. For instance, one extension might modify the validation logic in a manner that inadvertently breaks the functionality provided by the other.
To avoid such complications, it might be beneficial to assess whether both packages are necessary for your project. If your requirements are met by generating and validating JWTs within the same ecosystem, sticking to Security.Jwt and its validation extensions. However, if you need to validate JWTs from external sources, use Security.JwtExtensions instead.
However if you really need both, let me know
You're right, I don't need both. My case is fairly standard. I have a api and client living on the same domain (demo.whatever.tld) and keycloak next to it (on keycloak.whatever.tld). The api does request a token, and that token is send in the requests to my api (under /api/).
I guess I was just trying to make anything stick at all. But even only using the Jwks stuff from extensions (i did clean out the other dependencies to try) still gives me whats in the log below.
Someting else I noticed. The requests are waiting for a minute or more. That seems weird because even if the token is invalid that should be possible to verify in a few seconds.
Request starting HTTP/1.1 GET http://demo.myProduct.eu/api/TransportRegions - - -
2024-04-19 07:55:07
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1]
2024-04-19 07:55:07
Failed to validate the token.
2024-04-19 07:55:07
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. No security keys were provided to validate the signature.
2024-04-19 07:55:07
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignature(JsonWebToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
2024-04-19 07:55:07
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignatureAndIssuerSecurityKey(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
2024-04-19 07:55:07
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateJWSAsync(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
2024-04-19 07:55:07
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
2024-04-19 07:55:07
Bearer was not authenticated. Failure message: IDX10500: Signature validation failed. No security keys were provided to validate the signature.
2024-04-19 07:55:07
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001]
2024-04-19 07:55:07
1 candidate(s) found for the request path '/api/TransportRegions'
2024-04-19 07:55:07
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1005]
2024-04-19 07:55:07
Endpoint 'myProduct.Platform.Web.Controllers.TransportRegionsController.GetRegions (myProduct.Platform.Web)' with route pattern 'api/TransportRegions' is valid for the request path '/api/TransportRegions'
2024-04-19 07:55:07
dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1]
2024-04-19 07:55:07
Request matched endpoint 'myProduct.Platform.Web.Controllers.TransportRegionsController.GetRegions (myProduct.Platform.Web)'
2024-04-19 07:55:07
dbug: Microsoft.AspNetCore.Authorization.AuthorizationMiddleware[0]
2024-04-19 07:55:07
Policy authentication schemes did not succeed
2024-04-19 07:55:07
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
2024-04-19 07:55:07
Authorization failed. These requirements were not met:
2024-04-19 07:55:07
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
And since my container is not using persistent storage the key I find at '/root/.aspnet/DataProtection-Keys/' is always new.
Could this be related: https://github.com/dotnet/aspnetcore/issues/52075#issuecomment-1815025177 (although I fail to see why it would locally work then).
Update, if I set the BackChannelTimeout to a different value it takes that amount of time before the request fails, so its probably something with the httpclient that goes awry.
The validation keeps throwing "IDX10500: Signature validation failed. No security keys were provided to validate the signature."
This one is really baffling to me. I tried everything I could find, but what seems to be fairly simple is really hard to get working. Although it should be simple, your library is seemingly the only one that implements the whole 'validate against a jwksuri' -case.
Locally this works fine. The problem is that the container (based on 'mcr.microsoft.com/dotnet/aspnet:8.0') deployed will not work.
dotnet minimal api setup:
log:
cat /root/.aspnet/DataProtection-Keys/key-e92cdd27-bdba-48e6-a9f5-3dc207e-12223.xml