Let the client_credentials and jwt-bearer grants run without Protected Resource Metadata - #557
Merged
koic merged 1 commit intoSep 18, 2026
Conversation
…d Resource Metadata
## Motivation and Context
When a server publishes no Protected Resource Metadata, discovery takes the legacy 2025-03-26 path and `prm` is `nil`.
The authorization-code branch of `run!` allowed for that by passing `prm || {}` to `resolve_scope`,
but `run_client_credentials!` and `run_jwt_bearer!` passed `prm` as is, and `resolve_scope` then
called `prm["scopes_supported"]` on `nil`. Without a non-empty challenge scope, a `ClientCredentialsProvider` or
`CrossAppAccessProvider` pointed at such a server therefore failed with `NoMethodError` after discovery and before
the token request or the ID-JAG callback, instead of running its grant against the legacy authorization base
the way `Provider` does.
`resolve_scope` now treats a missing PRM as advertising no scopes, so the challenge scope or the provider's own scope applies,
and the authorization-code branch passes `prm` unchanged like the other two.
## How Has This Been Tested?
New tests in `test/mcp/client/oauth/flow_test.rb` run the `client_credentials` grant against a PRM-less server with metadata
at the origin, checking the provider's scope, the `resource`, and the recorded issuer, and run the `jwt-bearer` grant against
a server without any metadata, checking the default token endpoint, the assertion audience, the `resource`, and the recorded
issuer. Both raise `NoMethodError` against the previous library.
## Breaking Changes
None.
koic
deleted the
run_the_extension_grants_without_protected_resource_metadata
branch
September 18, 2026 15:12
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.
Motivation and Context
When a server publishes no Protected Resource Metadata, discovery takes the legacy 2025-03-26 path and
prmisnil. The authorization-code branch ofrun!allowed for that by passingprm || {}toresolve_scope, butrun_client_credentials!andrun_jwt_bearer!passedprmas is, andresolve_scopethen calledprm["scopes_supported"]onnil. Without a non-empty challenge scope, aClientCredentialsProviderorCrossAppAccessProviderpointed at such a server therefore failed withNoMethodErrorafter discovery and before the token request or the ID-JAG callback, instead of running its grant against the legacy authorization base the wayProviderdoes.resolve_scopenow treats a missing PRM as advertising no scopes, so the challenge scope or the provider's own scope applies, and the authorization-code branch passesprmunchanged like the other two.How Has This Been Tested?
New tests in
test/mcp/client/oauth/flow_test.rbrun theclient_credentialsgrant against a PRM-less server with metadata at the origin, checking the provider's scope, theresource, and the recorded issuer, and run thejwt-bearergrant against a server without any metadata, checking the default token endpoint, the assertion audience, theresource, and the recorded issuer. Both raiseNoMethodErroragainst the previous library.Breaking Changes
None.
Types of changes
Checklist