Stateless MCP auth: issuer-bound enrollment, JWKS refresh, audience pinning
MCP 2026-07-28 · CIMD first · DCR deprecated · RFC 9207 issuer validation · authorize every request
MCP client
native or web client
holds
- client_id by issuer
- PKCE verifier
- access tokens by issuer
- expected response iss
authorization server
issuer = auth.example.com
publishes
- /.well-known/
oauth-authorization-server
(RFC 8414)
- resolves CIMD client_id
- DCR only as fallback
- aud-pin via resource
(RFC 8707)
- /token + JWKS + iss
MCP server
notes.example.com
enforces
- aud == self.resource
- iss in allow-list
(RFC 9728)
- exp not past
- required scope
- 401/403 with
WWW-Authenticate
- no auth session cache
resource server logic
GET /.well-known/
oauth-protected-resource
POST /mcp
(validate, then dispatch)
scheduled refresh_jwks
"0 */6 * * *"
validate(token,
required_scope)
cache[iss] = {keys, ...}
JWKS cache
key: <iss>
value: {
keys: [
{kid: k_2026_03},
{kid: k_2026_04}
],
fetched_at: 1772668800
}
GET /.well-known/oauth-authorization-server
(1) RFC 8414 discovery
{issuer, CIMD support, jwks_uri, iss support}
client_id=https://client.example/client.json
(2) Client ID Metadata Document
AS fetches metadata; identity stays issuer-bound
/authorize + code_challenge + resource=...
(3) RFC 7636 PKCE + RFC 8707
authorization response iss, then token (aud, scope, kid)
Authorization: Bearer eyJ... (call tool)
(4) Every stateless MCP request validates bearer, issuer, audience, expiry, and scope
cron writes
validate reads