Prefer token endpoint auth method obtained during OAuth client registration
Opened this issue · 2 comments
Describe the bug
When doing an OAuth flow using dynamic client registration, the token_endpoint_auth_method returned in the registration data should be used to request a token, rather than the one from the OAuth authorization server metadata. Not doing this may cause an OAuth flow to fail if a strict server requires the method that was posted and used during client registration.
To Reproduce
Steps to reproduce the behavior:
- Use the code from the sample client (
src/examples/client/simpleOAuthClient.ts) which specifiestoken_endpoint_auth_method: 'client_secret_post'in theOAuthClientMetadata. - The client will register using
client_secret_post, and we assume that the server will confirm that in the registration response. - In
exchangeAuthorizationand inrefreshAuthorization(src/client/auth.ts), the following code is used:
// Determine and apply client authentication method
const supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? [];
const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
applyClientAuthentication(authMethod, clientInformation, headers, params);
and selectClientAuthMethod uses this check which takes the supported methods from the OAuth authorization server metadata, rather than the clientInformation:
if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
return "client_secret_basic";
}
- Server may reject the token response due to
client_secret_basicbeing used rather thanclient_secret_postsince the server may not need to honorclient_secret_basicanymore after the client was registered withclient_secret_post.
Expected behavior
Prefer the token_endpoint_auth_method from the client clientInformation that was obtained during registration, and only if it's unavailable fall back to the metadata from the OAuth authorization server.
Hitting this as well with our OAuth2 server. We always issue a client_secret, even if the token_endpoint_auth_method is set to none. MCP then tries to authenticate with a client_secret_basic method, but we reject it since the client expects none.