dotnet / dotnet/aspnetcore

Stale signing key cache results in 401 response during key rollover in JwtBearerHandler

Open
#28,948 14 comments 6 reactions 1 assignee Assigned to @blowdart View on GitHub
area-auth Needs: Design
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is your feature request related to a problem? Please describe.
Following a signing key rollover, it appears that `Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler` may incorrectly report an authentication failure (which results in a 401 Unauthorized response) in `HandleAuthenticateAsync` due to a stale local cache of the signing keys.

`Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler` relies on `Microsoft.IdentityModel.Protocols.IConfigurationManager` as a cache for the signing keys when validating the signature in JWT tokens. In `HandleAuthenticateAsync()`, when authentication fails due to `SecurityTokenSignatureKeyNotFoundException` (which may legitimately occur due to key rollovers), `JwtBearerHandler` simply calls `IConfigurationManager.RequestRefresh()`, which does not refresh the signing keys immediately. Instead, it sets a timestamp which causes the configuration to be refreshed beginning with the next request. The request in question will still fail at the authentication stage. The relevant code here:

https://github.com/dotnet/aspnetcore/blob/41eab27ef39706c5c08183c740eb0d5f3ab32df4/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs#L124-L128

### Describe the solution you'd like
From my point of view, upon encountering a `SecurityTokenSignatureKeyNotFoundException`, the signing keys should be refreshed immediately and signature validation should be attempted again with the refreshed keys, all within that same request lifetime. However, I suspect that the reason that this is not done is deliberate - as mentioned in https://github.com/dotnet/aspnetcore/issues/26504#issuecomment-702364883:

> This is about a request using a consistent configuration for all stages. We wouldn't want the config to change part way through or you could get inconsistent results.

But this actually results in incorrect 401 responses - the user should in fact be authenticated, and the system fails to authenticate the user purely due to some technical constraints that causes the authentication to be based on stale data. In a distributed system, this may result in a spike in 401 responses across the system when key rollover occurs - certainly a less than ideal situation.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.