@W-19861422 - token endpoint hardening#267
Merged
mattcfilbert merged 3 commits intomainfrom Mar 20, 2026
Merged
Conversation
Verify that the redirect_uri in the token request matches the redirect_uri used during the original authorization request, per OAuth 2.1 Section 4.1.3. Adds two test cases: mismatch returns 400 invalid_grant, match succeeds. Made-with: Cursor
Validates that client_id in the token request matches the client_id used at authorization, but only when client_id is present (public clients may omit it). Returns 400 invalid_grant on mismatch. Made-with: Cursor
…-19861422) Two OAuth 2.1 compliance fixes that strengthen protection against authorization code interception without requiring the full DCR redesign: 1. Validate redirect_uri at token exchange (OAuth 2.1 Section 4.1.3) The redirect_uri was stored on AuthorizationCode but never checked at token time. A mismatched redirect_uri now returns 400 invalid_grant. 2. Validate client_id at token exchange (when provided) If client_id is present in the token request (body or Basic Auth), it must match the client_id used at authorization. Uses Basic Auth credential identity as fallback to close the body-less header path. Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Template
Description
Two targeted hardening changes to the OAuth token endpoint that enforce standard OAuth 2.1 binding requirements. No new features or breaking changes — purely additive validation.
Change 1: Validate
redirect_uriat token exchangeWhen a client exchanges an authorization code for a token, the
redirect_uriin the token request must now match the one used at authorization time. Returns400 invalid_granton mismatch.Change 2: Validate
client_idat token exchange (conditional)When
client_idis present in the token request (body or Basic Auth header), it must match theclient_idused at authorization. Returns400 invalid_granton mismatch. Ifclient_idis absent, the check is skipped — public clients that omit it are unaffected.Motivation and Context
A security review (W-19861422) identified that the OAuth token endpoint was not enforcing two standard OAuth 2.1 requirements:
redirect_uribinding (OAuth 2.1 Section 4.1.3): The authorization code flow storesredirectUrion theAuthorizationCodeobject but never compared it at token exchange. An attacker who intercepts a code could exchange it using any redirect URI.client_idbinding: Theclient_idwas stored onAuthorizationCodebut similarly never verified at token time. The Basic Auth path was also a gap — a client authenticating via HTTP Basic without a bodyclient_idwould bypass the check entirely. The fix uses the credential-verified identity from Basic Auth as a fallback.PKCE remains the primary protection for public clients. These changes are defense-in-depth that align the implementation with the spec. The broader DCR architectural work remains scoped to the long-term Tableau identity system redesign.
Type of Change
How Has This Been Tested?
Five new test cases added to
tests/oauth/embedded-authz/oauth.test.ts, all exercising the full authorize → callback → token request flow (not mocked handlers):redirect_urimismatch → 400invalid_grant: 'Redirect URI mismatch'redirect_uri→ 200 success (regression)client_idmismatch → 400invalid_grant: 'Client ID mismatch'client_idin token request → 200 success (public client path unaffected)client_idmismatch (no bodyclient_id) → 400invalid_grant: 'Client ID mismatch'All 913 existing unit tests pass locally.
Related Issues
W-19861422
Checklist
npm run version. For example,use
npm run version:patchfor a patch version bump.environment variable or changing its default value.
Contributor Agreement
By submitting this pull request, I confirm that:
its Contribution Checklist.