Bind access tokens to an RFC 8707 resource indicator - #19
Draft
RhysSullivan wants to merge 1 commit into
Draft
Conversation
A client that names a resource at /oauth2/authorize now receives a token whose aud is that resource, and a refresh renews the same binding. This is what lets a dynamically registered MCP client reach a resource server that has never seen its client id. The consent page previously dropped the resource parameter, so only the login_hint fast path could carry it, and nothing downstream ever set a resource audience. Absent a resource indicator the prior behaviour stands: EMULATE_WORKOS_AUDIENCE when set, else the requesting client.
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.
A dynamically registered MCP client could not reach a resource server. The emulator issued tokens whose
audwas the DCR client's own id, while a resource server verifies against its own client id, so every token was refused asinvalid_tokenand re-authenticating just minted another wrong-audience client.Change
A client that sends an RFC 8707
resourceindicator to/oauth2/authorizenow gets a token bound to that resource. That is the point of the mechanism: the resource server admits the token without knowing anything about the client that asked for it.Three parts:
resourceis carried on the authorization code, so it survives to the token endpoint.login_hintfast path could carry a resource at all and nothing downstream ever set a resource audience.Precedence is
resource→EMULATE_WORKOS_AUDIENCE→ requesting client. Absent a resource indicator nothing changes for existing callers.Tests
binds an access token to the RFC 8707 resource a client asked forcovers the bound token, the refresh preserving the binding, and the unbound case still resolving to the requesting client. Confirmed to fail before the change (JWTClaimValidationFailed: unexpected "aud" claim value).16 tests pass in
@emulators/workos; the package lints with 0 errors.web#lintfails on this branch, but it fails identically on a cleanmain— pre-existing and unrelated to this change, which touches only@emulators/workos.Docs
skills/workos/SKILL.mdupdated for the new precedence. The other doc surfaces (README, web docs, CLI help) don't mention audience behaviour.