Drop confidential-client support (closes I-1)#25
Merged
Conversation
stevepridemore
added a commit
that referenced
this pull request
May 10, 2026
The server advertised client_secret_basic and client_secret_post in
discovery metadata, generated a random client_secret for confidential
registrations, and stored it plaintext in clients.json — but never
actually verified the secret at /oauth/token. The entire confidential
path was dead code that misadvertised a feature it didn't deliver.
Fix the misadvertisement by removing the path entirely:
- registerClient throws InvalidClientMetadataError for any
token_endpoint_auth_method other than "none"
- /oauth/register catches it and returns 400 invalid_client_metadata
- RegisteredClient.client_secret field removed
- RegisteredClient.token_endpoint_auth_method narrowed to "none"
- Discovery metadata advertises ["none"] only
All real clients (claude.ai web, Claude Desktop, Claude Code) already
use PKCE + token_endpoint_auth_method=none, which became mandatory in
PR #18. No on-disk migration is needed: existing clients.json entries
are all "none" already, and any stray client_secret strings will be
ignored at runtime since nothing reads them anymore.
If server-to-server / machine-to-machine clients are wanted in the
future, they should be re-introduced as one coherent feature:
client_credentials grant + hashed client_secret + verification +
re-advertised metadata. See docs/REMOTE.md for the deferred design
note.
Closes finding I-1 from docs/internal/THREAT-MODEL.md.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
The server advertised
client_secret_basicandclient_secret_postin discovery metadata and generated a randomclient_secretfor confidential registrations — but/oauth/tokennever actually verified it. The whole path was dead code that misadvertised a feature it didn't deliver.This PR closes finding I-1 by removing the path entirely rather than building out hashing + verification for a feature with no current consumer.
registerClientthrowsInvalidClientMetadataErrorfor anytoken_endpoint_auth_methodother than"none"/oauth/registercatches it and returns400 invalid_client_metadataRegisteredClient.client_secretfield removedRegisteredClient.token_endpoint_auth_methodnarrowed to"none"["none"]onlydocs/REMOTE.mdcovering the deferred server-to-server / machine-to-machine case (requiresclient_credentialsgrant + hashed secrets + verification, all together)All real clients (claude.ai web, Claude Desktop, Claude Code) already use PKCE +
token_endpoint_auth_method=none, which became mandatory in #18. No on-disk migration is needed.Test plan
npm run buildcleannpx vitest run src/shared/oauth.test.ts— 49 passing (7 new for the new "confidential clients no longer supported" describe block)curl -sk https://graph-memory.doublec.biz/.well-known/oauth-authorization-server | jq .token_endpoint_auth_methods_supportedreturns["none"]POST /oauth/registerwith"token_endpoint_auth_method": "client_secret_basic"returns 400invalid_client_metadata🤖 Generated with Claude Code