[Server] feat: relax StrictOidcDiscoveryMetadataPolicy and add Dynamic Client Registration middleware (RFC 7591)#269
Conversation
|
There is an examples for microsoft connection. There is a trouble not only with OIDC discovery. https://github.com/modelcontextprotocol/php-sdk/blob/main/examples/server/oauth-microsoft/MicrosoftOidcMetadataPolicy.php Examples should be also updated if alternative OIDC discovery is accepted. There is also alternative way - in case when code_challenge_methods_supported is missed we can set it's value to default S256 |
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
Good point — I've removed LenientOidcDiscoveryMetadataPolicy and relaxed StrictOidcDiscoveryMetadataPolicy to accept missing code_challenge_methods_supported. If the field is present it's still validated strictly; if absent, the downstream OAuthProxyMiddleware already defaults to ['S256']. The interface stays for custom policies (like the Microsoft example). |
|
is the |
i guess just as an example how to implement OidcDiscoveryMetadataPolicyInterface |
|
I thought about this more, and I think my earlier comment was not precise enough. I agree we should support real-world providers like Microsoft that omit I would prefer to:
That keeps the naming and behavior clearer: |
|
Hi, The goal of the MCP SDK should be to implement the MCP protocol (JSON-RPC, tools, resources, prompts); not to become an OAuth server. The spec says the server must support OAuth, but that doesn't mean the SDK itself needs to embed a full OAuth implementation. Bundling Dynamic Client Registration (RFC 7591) directly into the SDK is a nonsense to me. |
|
Hi @Spomky, Providing something out of the box doesn't mean that we have to use it in context of Symfony Framework, Laravel etc. |
There was a problem hiding this comment.
Pull request overview
Adds HTTP-transport OAuth enhancements to improve compatibility with real-world OIDC providers and to support OAuth 2.0 Dynamic Client Registration as required by MCP servers.
Changes:
- Introduce
LenientOidcDiscoveryMetadataPolicyas an alternative to the strict discovery metadata validator. - Add
ClientRegistrationMiddleware(PSR-15) +ClientRegistrarInterfaceto implement RFC 7591 registration handling and metadata enrichment. - Update the Microsoft OAuth example to use the new built-in lenient policy and remove the example-specific policy.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/Server/Transport/Http/OAuth/OidcDiscoveryTest.php | Adds coverage ensuring lenient policy accepts missing code_challenge_methods_supported. |
| tests/Unit/Server/Transport/Http/OAuth/LenientOidcDiscoveryMetadataPolicyTest.php | New unit tests for lenient discovery metadata validation rules. |
| tests/Unit/Server/Transport/Http/Middleware/ClientRegistrationMiddlewareTest.php | New unit tests for RFC 7591 middleware behavior and metadata enrichment. |
| src/Server/Transport/Http/OAuth/LenientOidcDiscoveryMetadataPolicy.php | New metadata policy that relaxes the strict requirement for PKCE method listing. |
| src/Server/Transport/Http/OAuth/ClientRegistrarInterface.php | New SPI for pluggable dynamic client registration implementations. |
| src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php | New PSR-15 middleware handling /register and enriching auth server metadata. |
| src/Exception/ClientRegistrationException.php | New exception type for registrar failures. |
| examples/server/oauth-microsoft/tests/Unit/MicrosoftOidcMetadataPolicyTest.php | Removes example-specific tests tied to the removed policy. |
| examples/server/oauth-microsoft/server.php | Switches example to LenientOidcDiscoveryMetadataPolicy. |
| examples/server/oauth-microsoft/README.md | Updates documentation to match the new built-in policy usage. |
| examples/server/oauth-microsoft/MicrosoftOidcMetadataPolicy.php | Removes the example-specific metadata policy implementation. |
| CHANGELOG.md | Documents the two new additive features. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/Server/Transport/Http/OAuth/LenientOidcDiscoveryMetadataPolicy.php
Outdated
Show resolved
Hide resolved
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… middleware (RFC 7591) - Add LenientOidcDiscoveryMetadataPolicy for providers that omit code_challenge_methods_supported (e.g. FusionAuth, Microsoft Entra ID) - Keep StrictOidcDiscoveryMetadataPolicy RFC-aligned - Add ClientRegistrationMiddleware handling POST /register and enriching /.well-known/oauth-authorization-server with registration_endpoint - Update Microsoft example to use built-in LenientOidcDiscoveryMetadataPolicy
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review comment: the LenientOidcDiscoveryMetadataPolicy bullet was a behavioral note, not a file entry. Inline it into the server.php description to keep the Files list consistent.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
- Decode JSON with assoc=true for registrar data so nested objects are associative arrays, not stdClass instances - Add Cache-Control: no-store to all error responses (400), not just the success response (201) - Rewind response body stream before returning unmodified response when metadata is not valid JSON, preventing empty body on read
- Revert spurious .gitignore trailing newline - Use JSON_THROW_ON_ERROR consistently in enrichAuthServerMetadata() - Add comment clarifying the second json_decode in handleRegistration() - Assert Cache-Control: no-store on registrar exception error response - Add test for non-object JSON body in metadata enrichment path - Extract createPlainTextHandler helper for non-JSON response tests
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/Server/Transport/Http/Middleware/ClientRegistrationMiddleware.php
Outdated
Show resolved
Hide resolved
Treat JSON list arrays (e.g. [] or ["..."]) as invalid metadata in enrichAuthServerMetadata() to prevent corrupting the response shape by adding registration_endpoint to a non-object.
Add two features to the HTTP transport layer:
code_challenge_methods_supported
Motivation and Context
LenientOidcDiscoveryMetadataPolicy: Several identity providers (FusionAuth, Microsoft Entra ID) omit code_challenge_methods_supported from
their OIDC discovery response despite fully supporting PKCE with S256. The existing OidcDiscoveryMetadataPolicy rejects these responses,
making it impossible to use the SDK's OAuth transport with those providers without a custom policy. This provides a ready-made workaround.
ClientRegistrationMiddleware: The MCP specification requires servers to support OAuth 2.0 Dynamic Client Registration (RFC 7591) so that MCP
clients can register themselves automatically. This middleware handles POST /register by delegating to a ClientRegistrarInterface
implementation and enriches /.well-known/oauth-authorization-server responses with the registration_endpoint. The ClientRegistrarInterface
keeps the actual registration logic (e.g. calling FusionAuth, storing in a database) pluggable.
How Has This Been Tested?
required fields, empty strings, non-array input
enrichment with registration_endpoint, Cache-Control preservation, non-200 passthrough, non-matching route passthrough, empty localBaseUrl
rejection, trailing slash normalization
Breaking Changes
None. Both features are purely additive — new classes and interfaces only.
Types of changes
Checklist
Additional context
handler classes in tests)
advanced