Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: JWKS Request should not be duplicated headers added by filters #1924

Merged
merged 2 commits into from
Feb 4, 2025

Conversation

sdelamo
Copy link
Contributor

@sdelamo sdelamo commented Feb 3, 2025

Close: #1881

We have two implementations of JwkSetFetcher: CacheableJwkSetFetcher and ReactorJwkSetFetcher. JwkSetFetcherdefines a bean responsible for sending an HTTP request to a remote authorization server to fetch the public keys, the JSON Web Key Set (JWKS).

The former is not affected, but the latter, which uses Project Reactor Mono::cacheInvalidateIf to cache requests, had a bug that manifested if a client filter added extra HTTP headers to a request sent to the authorization server. For example, if you were using Micronaut Open Telemetry integration. The HTTP Client filter in Micronaut Open Telemetry adds HTTP Headers. Before this fix, the header value would keep getting added.

@sdelamo sdelamo requested a review from yawkat February 3, 2025 14:32
@sdelamo sdelamo changed the title reproducer of 1881 fix: JWKS Request should not be duplicated headers added by filters Feb 3, 2025
@sdelamo sdelamo requested a review from n0tl3ss February 3, 2025 14:45
.cacheInvalidateIf(JwksCacheEntry::isExpired);
.defaultIfEmpty(new JWKSet())
.map(jwksSet -> instantiateCacheEntry(cacheKey, jwksSet))
.doOnNext(entry -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont think this works, it will only be called once. you should put it into the cacheInvalidateIf parameter instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If remove the doOnNext and I do

            .cacheInvalidateIf(entry -> {
                if (entry.isExpired()) {
                    cache.remove(cacheKey);
                }
                return entry.isExpired();
            });

The test fails 7 headers instead of the expected five.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch doesn't work either, though. As soon as the first expires, you're going to have multiple JWKSets for the same key, defeating the point of the caching.

This class is deprecated, does it need to be fixed? A proper cache implementation with eviction here would be more complicated than this PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there. i found a simple solution after all

@sdelamo sdelamo requested a review from yawkat February 3, 2025 15:42
.cacheInvalidateIf(JwksCacheEntry::isExpired);
.defaultIfEmpty(new JWKSet())
.map(jwksSet -> instantiateCacheEntry(cacheKey, jwksSet))
.doOnNext(entry -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there. i found a simple solution after all

@sdelamo
Copy link
Contributor Author

sdelamo commented Feb 4, 2025

there. i found a simple solution after all

Thanks.

This class is deprecated, does it need to be fixed?

Yes. it needs to be fixed.

A proper cache implementation with eviction here would be more complicated than this PR

@yawkat a proper implementation already exists based on Micronaut Cache.

@sdelamo sdelamo merged commit b919bbb into 4.12.x Feb 4, 2025
19 checks passed
@sdelamo sdelamo deleted the issue-1881 branch February 4, 2025 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Default jwk set fetcher implementation leading to "Request Entity Too Large"
2 participants