Describe the bug
When AuthorizationServerSettings.multipleIssuersAllowed(true) is set, the two metadata endpoint filters use opposite and incompatible well-known URL shapes for an issuer that has a path component, so only one of
the two OpenID Connect discovery locations defined for path-bearing issuers is served.
OAuth2AuthorizationServerMetadataEndpointFilter matches the path-insertion shape /.well-known/oauth-authorization-server/** (well-known segment first, issuer path appended):
https://github.com/spring-projects/spring-security/blob/43f958e0587e07bcb322194ce2acf9ad921a5b88/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2A
uthorizationServerMetadataEndpointFilter.java#L131
OidcProviderConfigurationEndpointFilter matches only the path-append shape /**/.well-known/openid-configuration (issuer path first, well-known segment last):
https://github.com/spring-projects/spring-security/blob/43f958e0587e07bcb322194ce2acf9ad921a5b88/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/Oi
dcProviderConfigurationEndpointFilter.java#L136
As a result, for an issuer such as https://host/tenant1:
This asymmetry breaks interoperability with the Model Context Protocol (MCP) authorization spec, which requires clients to try the OIDC path-insertion location and lists it ahead of the append location. From
https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization (section "Authorization Server Metadata Discovery"):
"For issuer URLs with path components (e.g., https://auth.example.com/tenant1), clients MUST try endpoints in the following priority order:
- OAuth 2.0 Authorization Server Metadata with path insertion: https://auth.example.com/.well-known/oauth-authorization-server/tenant1
- OpenID Connect Discovery 1.0 with path insertion: https://auth.example.com/.well-known/openid-configuration/tenant1
- OpenID Connect Discovery 1.0 path appending: https://auth.example.com/tenant1/.well-known/openid-configuration"
That same MCP section states the approach is based on RFC 8414 Section 3.1 ("Authorization Server Metadata Request") and RFC 8414 Section 5 ("Compatibility Notes") for OpenID Connect Discovery 1.0 interoperability.
So priority #2 — the OIDC path-insertion location — is exactly what OidcProviderConfigurationEndpointFilter does not serve, while the OAuth filter already serves the analogous insertion location for its own
document.
To Reproduce
- Configure a SecurityFilterChain that registers OAuth2AuthorizationServerMetadataEndpointFilter and OidcProviderConfigurationEndpointFilter, with
AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build() available on the per-request AuthorizationServerContext (issuer e.g. http://host:8080/tenant1).
- Start the server.
- GET http://host:8080/.well-known/oauth-authorization-server/tenant1 — returns 200 (OAuth metadata, path insertion).
- GET http://host:8080/tenant1/.well-known/openid-configuration — returns 200 (OIDC metadata, path append).
- GET http://host:8080/.well-known/openid-configuration/tenant1 — returns 404 (OIDC metadata, path insertion), even though an MCP client following the spec's priority order tries this URL before the append form.
Expected behavior
In multi-issuer mode, OidcProviderConfigurationEndpointFilter should also serve the OIDC path-insertion location /.well-known/openid-configuration/**, symmetric with OAuth2AuthorizationServerMetadataEndpointFilter,
so that GET https://host/.well-known/openid-configuration/tenant1 returns the same document as the path-append location. Alternatively (or additionally), the filter should expose a way to configure its
RequestMatcher; it is currently final with a private final RequestMatcher and only setProviderConfigurationCustomizer is available, so applications cannot add the insertion location without wrapping/rewriting the
request.
The document body itself needs no change: the filter builds it solely from AuthorizationServerContextHolder.getContext().getIssuer(), so only the request matching (and the corresponding multi-issuer issuer
resolution, which must recognize that for the insertion shape the issuer path follows the well-known segment rather than preceding it) needs to handle both shapes.
Describe the bug
When AuthorizationServerSettings.multipleIssuersAllowed(true) is set, the two metadata endpoint filters use opposite and incompatible well-known URL shapes for an issuer that has a path component, so only one of
the two OpenID Connect discovery locations defined for path-bearing issuers is served.
OAuth2AuthorizationServerMetadataEndpointFilter matches the path-insertion shape /.well-known/oauth-authorization-server/** (well-known segment first, issuer path appended):
https://github.com/spring-projects/spring-security/blob/43f958e0587e07bcb322194ce2acf9ad921a5b88/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2A
uthorizationServerMetadataEndpointFilter.java#L131
OidcProviderConfigurationEndpointFilter matches only the path-append shape /**/.well-known/openid-configuration (issuer path first, well-known segment last):
https://github.com/spring-projects/spring-security/blob/43f958e0587e07bcb322194ce2acf9ad921a5b88/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/Oi
dcProviderConfigurationEndpointFilter.java#L136
As a result, for an issuer such as https://host/tenant1:
This asymmetry breaks interoperability with the Model Context Protocol (MCP) authorization spec, which requires clients to try the OIDC path-insertion location and lists it ahead of the append location. From
https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization (section "Authorization Server Metadata Discovery"):
"For issuer URLs with path components (e.g., https://auth.example.com/tenant1), clients MUST try endpoints in the following priority order:
That same MCP section states the approach is based on RFC 8414 Section 3.1 ("Authorization Server Metadata Request") and RFC 8414 Section 5 ("Compatibility Notes") for OpenID Connect Discovery 1.0 interoperability.
So priority #2 — the OIDC path-insertion location — is exactly what OidcProviderConfigurationEndpointFilter does not serve, while the OAuth filter already serves the analogous insertion location for its own
document.
To Reproduce
AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build() available on the per-request AuthorizationServerContext (issuer e.g. http://host:8080/tenant1).
Expected behavior
In multi-issuer mode, OidcProviderConfigurationEndpointFilter should also serve the OIDC path-insertion location /.well-known/openid-configuration/**, symmetric with OAuth2AuthorizationServerMetadataEndpointFilter,
so that GET https://host/.well-known/openid-configuration/tenant1 returns the same document as the path-append location. Alternatively (or additionally), the filter should expose a way to configure its
RequestMatcher; it is currently final with a private final RequestMatcher and only setProviderConfigurationCustomizer is available, so applications cannot add the insertion location without wrapping/rewriting the
request.
The document body itself needs no change: the filter builds it solely from AuthorizationServerContextHolder.getContext().getIssuer(), so only the request matching (and the corresponding multi-issuer issuer
resolution, which must recognize that for the insertion shape the issuer path follows the well-known segment rather than preceding it) needs to handle both shapes.