Skip to content

fix(auth): cap JWT token-exchange lifetime to subject expiry#5039

Closed
vigneshio wants to merge 1 commit into
apache:mainfrom
vigneshio:fix/token-exchange-ttl-no-infinite-refresh
Closed

fix(auth): cap JWT token-exchange lifetime to subject expiry#5039
vigneshio wants to merge 1 commit into
apache:mainfrom
vigneshio:fix/token-exchange-ttl-no-infinite-refresh

Conversation

@vigneshio

Copy link
Copy Markdown
Contributor

Internal JWT token exchange no longer issues an access token that outlives the subject token.

Previously each exchange reset expiry to a full maxTokenGeneration window, so a valid (or stolen) access token could be refreshed indefinitely. Exchanged tokens are now capped to the remaining subject lifetime (and still to maxTokenGeneration).

Also stop treating a non-Basic Authorization header as client credentials for the token endpoint; exchange with subject_token alone is allowed but cannot extend session lifetime.

Token exchange previously minted a new access token with a full
maxTokenGeneration window, so a valid subject token could be exchanged
indefinitely to refresh session lifetime. Cap exchanged tokens to the
remaining subject lifetime (still bounded by maxTokenGeneration).

Also stop treating a non-Basic Authorization header as authentication
for the token endpoint; exchange is allowed with subject_token alone
but cannot outlive that subject.
@vigneshio
vigneshio force-pushed the fix/token-exchange-ttl-no-infinite-refresh branch from 5826676 to 14efb2c Compare July 16, 2026 13:27

@adutra adutra left a comment

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.

@vigneshio I'm afraid we can't accept this PR 😞

Exchanged tokens are now capped to the remaining subject lifetime

In a "real" token exchange grant, that's indeed the best thing to do. However, here we are abusing the token exchange grant for something it wasn't designed for: refreshing tokens. This is exactly how the Iceberg OAuth2 client behaves. IOW, it's not a bug, it's a feature 😄

stop treating a non-Basic Authorization header as client credentials for the token endpoint;

Same thing: this is indeed non-standard, but that's how the Iceberg client refreshes tokens by default: the Authorization header will contain Bearer <token> and <token> will be identical to the subject token.

@vigneshio

Copy link
Copy Markdown
Contributor Author

@vigneshio I'm afraid we can't accept this PR 😞

Exchanged tokens are now capped to the remaining subject lifetime

In a "real" token exchange grant, that's indeed the best thing to do. However, here we are abusing the token exchange grant for something it wasn't designed for: refreshing tokens. This is exactly how the Iceberg OAuth2 client behaves. IOW, it's not a bug, it's a feature 😄

stop treating a non-Basic Authorization header as client credentials for the token endpoint;

Same thing: this is indeed non-standard, but that's how the Iceberg client refreshes tokens by default: the Authorization header will contain Bearer <token> and <token> will be identical to the subject token.

Thanks for the context, @adutra - Makes sense - closing this out.

@vigneshio vigneshio closed this Jul 17, 2026
@github-project-automation github-project-automation Bot moved this from PRs In Progress to Done in Basic Kanban Board Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants