Skip to content

Grant default aud when resource is absent#4805

Merged
blkt merged 3 commits intomainfrom
fix/add-missing-audience
Apr 14, 2026
Merged

Grant default aud when resource is absent#4805
blkt merged 3 commits intomainfrom
fix/add-missing-audience

Conversation

@blkt
Copy link
Copy Markdown
Contributor

@blkt blkt commented Apr 14, 2026

The TokenHandler only granted an audience claim when the client included the RFC 8707 resource parameter. Clients that omit this optional parameter received a token with an empty aud, which caused VirtualMCPServer to reject every token its own auth server issued: the incoming OIDC validator requires audience to be set and rejects tokens that do not carry a matching claim.

When no resource parameter is present and AllowedAudiences contains exactly one entry, the handler now defaults to granting that audience. The intended audience is unambiguous in that case, and AllowedAudiences is always non-empty (enforced at config validation time). The defaulting is restricted to authorization_code grants; for refresh_token grants fosite carries the originally-granted audience forward through the stored session automatically, so re-granting would conflict with its matching strategy.

Fixes #4794

@blkt blkt self-assigned this Apr 14, 2026
@github-actions github-actions bot added the size/XS Extra small PR: < 100 lines changed label Apr 14, 2026
blkt added a commit that referenced this pull request Apr 14, 2026
An explicit empty `resource=` parameter was hitting the
`len(resources) == 1` branch and calling `GrantAudience("")`, producing
`aud:[""]` instead of the intended default. The fix is to treat an empty
string the same as an absent parameter by adding `&& resources[0] != ""`
to the condition, so an explicit empty value falls through to the
defaulting `else if` branch. A test covering this case is also added.

The comment on the defaulting branch overstated the invariant by
attributing safety to config-validation-time enforcement. The actual
safety comes from the `len == 1` guard on the same line; the comment is
updated to reflect that.
@github-actions github-actions bot added size/S Small PR: 100-299 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Apr 14, 2026
blkt added 3 commits April 14, 2026 15:49
The `TokenHandler` only granted an audience claim when the client
included the RFC 8707 `resource` parameter. Clients that omit this
optional parameter received a token with an empty `aud`, which caused
`VirtualMCPServer` to reject every token its own auth server issued:
the incoming OIDC validator requires `audience` to be set and rejects
tokens that do not carry a matching claim.

When no `resource` parameter is present and `AllowedAudiences` contains
exactly one entry, the handler now defaults to granting that audience.
The intended audience is unambiguous in that case, and `AllowedAudiences`
is always non-empty (enforced at config validation time). The defaulting
is restricted to `authorization_code` grants; for `refresh_token` grants
fosite carries the originally-granted audience forward through the stored
session automatically, so re-granting would conflict with its matching
strategy.

Fixes #4794
An explicit empty `resource=` parameter was hitting the
`len(resources) == 1` branch and calling `GrantAudience("")`, producing
`aud:[""]` instead of the intended default. The fix is to treat an empty
string the same as an absent parameter by adding `&& resources[0] != ""`
to the condition, so an explicit empty value falls through to the
defaulting `else if` branch. A test covering this case is also added.

The comment on the defaulting branch overstated the invariant by
attributing safety to config-validation-time enforcement. The actual
safety comes from the `len == 1` guard on the same line; the comment is
updated to reflect that.
The three separate tests covering the `aud` claim behaviour of
`TokenHandler` shared identical structure. Merge them into a single
`TestTokenHandler_AudienceClaim` table-driven test with subtests for
the explicit-resource, absent-resource, and explicit-empty-resource
cases. Also upgrades the former `TestTokenHandler_ResourceParameter`,
which only asserted a 200 response, to verify the `aud` claim in the
issued JWT.
@blkt blkt force-pushed the fix/add-missing-audience branch from 8f20d44 to 89a40d6 Compare April 14, 2026 13:49
@github-actions github-actions bot added size/S Small PR: 100-299 lines changed and removed size/S Small PR: 100-299 lines changed labels Apr 14, 2026
@blkt
Copy link
Copy Markdown
Contributor Author

blkt commented Apr 14, 2026

Test failures are unrelated with the change, I'll fix them anyway in a separate branch.
I'm merging this! 🚀

@blkt blkt merged commit 25fe475 into main Apr 14, 2026
23 of 24 checks passed
@blkt blkt deleted the fix/add-missing-audience branch April 14, 2026 14:05
jhrozek added a commit that referenced this pull request Apr 14, 2026
The fix in #4805 defaults the aud claim to the sole AllowedAudiences
entry when clients omit the RFC 8707 resource parameter, but only
included unit tests. Add an end-to-end integration test that verifies
the full OAuth flow (authorize -> callback -> token exchange -> JWT
validation) produces the correct audience when resource is omitted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jhrozek added a commit that referenced this pull request Apr 14, 2026
…4818)

The fix in #4805 defaults the aud claim to the sole AllowedAudiences
entry when clients omit the RFC 8707 resource parameter, but only
included unit tests. Add an end-to-end integration test that verifies
the full OAuth flow (authorize -> callback -> token exchange -> JWT
validation) produces the correct audience when resource is omitted.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Embedded auth server issues tokens without audience claim when client omits RFC 8707 resource parameter

2 participants