feat(sep-1932): DPoP refresh token binding - #524
Open
nbarbettini wants to merge 2 commits into
Open
nbarbettini wants to merge 2 commits into
nbarbettini wants to merge 2 commits into
Conversation
RFC 9449 §5 binds a public client's refresh token to the DPoP key from the code exchange. The test authorization server now issues and rotates those tokens, and auth/dpop-refresh checks the client proves the same key. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
commit: |
nbarbettini
marked this pull request as ready for review
September 25, 2026 13:25
This branch has not been deployed
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.
Discussed here: https://discord.com/channels/1358869848138059966/1552316422951149639
Motivation and Context
Refresh tokens are long-lived credentials that may remain on a client device for months. If one is stolen, it can be exchanged repeatedly for new access tokens. RFC 9449 protects public DPoP clients by binding issued refresh tokens to the same key used at the token endpoint.
This change adds a client check for that requirement. The test authorization server can now issue and rotate refresh tokens on an opt-in basis. When a client uses one, it must present a valid DPoP proof for the original key.
Using refresh tokens remains optional. The check is SKIPPED when the client does not use the issued refresh token, and fails only when a refresh is attempted without a valid proof or with a different key.
Refresh is exercised within the existing
auth/dpopscenario. This keeps the full OAuth flow in one scenario and avoids duplicated setup or wall-clock expiry waits. The DPoP fixture explicitly registers a public client, and failed refresh observations remain sticky so a later successful retry cannot hide an earlier violation.How Has This Been Tested?
Breaking Changes
No breaking changes... if you are already doing DPoP correctly 😉
Clients participating in the DPoP extension may receive a new FAILURE if they use a refresh token without proving possession of the key to which it is bound. Clients that do not use refresh tokens are unaffected.
Types of changes
Checklist