Skip to content

Core: Fix optionalOAuthParams dropped during non-exchange token refresh#16023

Open
bharos wants to merge 1 commit intoapache:mainfrom
bharos:fix/oauth2-optional-params-refresh
Open

Core: Fix optionalOAuthParams dropped during non-exchange token refresh#16023
bharos wants to merge 1 commit intoapache:mainfrom
bharos:fix/oauth2-optional-params-refresh

Conversation

@bharos
Copy link
Copy Markdown
Contributor

@bharos bharos commented Apr 17, 2026

Fixes #16022

When exchangeEnabled is false, both refreshExpiredToken() and the static refreshToken() were calling fetchToken() with an empty map instead of forwarding optionalOAuthParams (which carries audience, resource, scope).

This was introduced in #14059 when the deprecated 5-arg fetchToken() overloads were removed and the 6-arg calls were inlined with ImmutableMap.of() instead of the available optionalOAuthParams.

The initial token fetch passes the params correctly, so the first token works. After expiry, the refreshed token is missing the audience/scope, causing 401/403 errors.

Fix: Pass optionalOAuthParams instead of ImmutableMap.of() / Map.of() in the two non-exchange branches.

Tests: Two new tests in TestOAuth2Util verify that audience appears in the token request form data for both the expired-token and proactive-refresh paths.

…sh (apache#16022)

When token-exchange-enabled=false, the non-exchange refresh paths in both
refreshToken() and refreshExpiredToken() passed ImmutableMap.of() instead
of the available optionalOAuthParams. This caused audience, resource, and
other optional OAuth parameters to be silently dropped on every token
refresh after the initial fetch.

Fix: pass optionalOAuthParams at both call sites instead of ImmutableMap.of().
@github-actions github-actions bot added the core label Apr 17, 2026
@bharos
Copy link
Copy Markdown
Contributor Author

bharos commented Apr 17, 2026

cc @adutra please review , thanks!

@singhpk234 singhpk234 self-requested a review April 17, 2026 22:29
argThat(
formData ->
CLIENT_CREDENTIALS.equals(formData.get(GRANT_TYPE))
&& audience.equals(formData.get("audience"))),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's a bit odd to have the audience parameter propagated on a client_credentials grant request, but I guess it's too convoluted to distinguish which optional parameters should be included depending on the grant. And most IDPs would just ignore this parameter, I guess (except Okta / Auth0).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also, shouldn't you assert that the scope is present too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Core: optionalOAuthParams (audience, resource) dropped during non-exchange token refresh

2 participants