# AuthPlane — full context dump > Open-source, self-hosted OAuth 2.1 authorization server purpose-built for the Model Context Protocol (MCP). One Go binary, alongside your MCP server, so tokens never leave your perimeter. ## What it is AuthPlane is the authorization layer for MCP servers. It issues, validates, and revokes the OAuth 2.1 tokens agents present when they call your MCP tools. It federates to your existing identity provider (Google, Okta, Entra ID, Auth0, or any OIDC-compliant provider) so users authenticate the way they already do, and it records every delegation hop in an audit log so you can prove who authorized what after the fact. - **License**: AGPL-3.0 (server), Apache-2.0 (SDKs). - **Ports**: OAuth endpoints on `:9000`, Admin UI on `:9001/admin/ui/`. - **Deploy**: single Go binary, Docker Compose, or Kubernetes via Helm chart at `oci://ghcr.io/authplane/charts/authplane`. - **Status**: v0.2.0 — verified end-to-end against Claude Desktop, Claude Code, and MCP Inspector (https://github.com/AuthPlane/authserver/blob/main/docs/reference/mcp-client-compatibility.md). No SOC 2 certification — self-hosted software is your organization's certification. ## Standards implemented MCP Authorization specification (2026-07-28) — Client ID Metadata Documents, RFC 9207 issuer identification, Protected Resource Metadata served by the AS, Enterprise-Managed Authorization discovery — plus: - OAuth 2.1 (draft-ietf-oauth-v2-1) - PKCE — RFC 7636 (mandatory S256) - Client Credentials — RFC 6749 §4.4 - JSON Web Key — RFC 7517 - JWT Bearer — RFC 7523 - Dynamic Client Registration — RFC 7591 - Token Introspection — RFC 7662 - Token Revocation — RFC 7009 - OAuth Authorization Server Metadata — RFC 8414 - Token Exchange — RFC 8693 (agent delegation) - Resource Indicators — RFC 8707 - JWT Access Tokens — RFC 9068 - DPoP — RFC 9449 - Problem Details for HTTP APIs — RFC 9457 - OAuth 2.0 Security BCP — RFC 9700 - Protected Resource Metadata — RFC 9728 - Client ID Metadata Document (CIMD) — IETF draft Full compliance matrix: https://docs.authplane.ai/reference/rfc-compliance/ ## Quickstart in one docker run ``` docker run -p 9000:9000 -p 9001:9001 \ -e AUTHPLANE_ADMIN_API_KEY=$(openssl rand -hex 32) \ -e AUTHPLANE_SESSION_SECRET=$(openssl rand -hex 32) \ -v authserver-data:/data \ authplane/authserver:latest serve ``` OAuth on `localhost:9000`, Admin UI on `localhost:9001/admin/ui/`. Docs quickstart: https://docs.authplane.ai/quickstart/ --- ## Blog posts (13 published) --- # DPoP for MCP servers: what it protects, what it costs - Published: 2026-08-26 - Tag: SECURITY - URL: https://authplane.ai/blog/dpop-for-mcp-servers/ - Excerpt: DPoP (RFC 9449) makes a copied token useless without the key it's bound to. What that buys you for agents, what it doesn't cover, and what it costs to run. *Bearer tokens treat whoever holds the token as authorized. For agents that copy tokens across processes, logs, and tool calls, that assumption is the problem. DPoP fixes one part of it, and gets credited for several it doesn't touch.* ## TL;DR - A bearer token is a house key: whoever holds it gets in. DPoP (RFC 9449) binds the token to a key the client proves it holds, so a copied token on its own stops working. - That matters for agents, which spread tokens across sub-agents, logs, and tool calls in ways a single browser session never did. - DPoP isn't free (per-request signing, state to track replay), and it isn't agent identity or delegation. It answers one question: is this the client the token was issued to? An OAuth bearer token works like a house key. Whoever holds it gets in, and the lock doesn't care how they got it. That's fine when one browser session holds one token behind TLS. It's a different situation when an autonomous agent passes tokens between sub-agents, writes them to logs, and hands them to a dozen tools an hour. Each of those is a place a token can leak, and with bearer semantics a leaked token is a working credential until it expires. DPoP (Demonstrating Proof of Possession, RFC 9449) changes the acceptance rule. Instead of "present the token," it becomes "present the token and prove you hold the key it's bound to." A copied token, by itself, stops working. It's easy to credit DPoP with more than it does, so precision helps: it solves one problem well, and gets blamed or praised for several others it never touches. ## What DPoP actually does The client generates a key pair and keeps the private key. On each request it sends a DPoP proof: a short JWT signed with that private key, carrying the HTTP method (`htm`), the request URI minus its query string and fragment (`htu`), a timestamp (`iat`), a unique ID (`jti`), and, once it has an access token, a hash of it (`ath`). The authorization server binds the issued token to the thumbprint of the public key. The resource server then checks, on every call, that the proof is signed by the key the token is bound to and that the method and path match. The security boundary is simple to state. Holding the token is no longer enough. You also need the private key, and the private key never leaves the client. Pull a token out of a log and you still can't use it, because you can't sign a fresh proof for it. ## Why agents change the threat model Bearer semantics were settled when a token usually lived in one place for one session, and the main risk was that place being stolen. Agents break those assumptions in specific ways: **Tokens fan out.** A planner agent hands tokens to sub-agents and tools, multiplying the copies sitting in memory and moving over the wire. **Tokens land in logs.** Agent frameworks log requests, traces, and tool calls freely, and tokens end up in plaintext logs and observability pipelines that a lot of people can read. **Workflows run long.** An agent can hold a token for hours, which widens the window in which a leaked copy is still good. DPoP addresses the shared root cause: it makes a copied token inert. Wherever the token leaks, the leak is worth much less, because the copy can't sign proofs, and that's the reason to turn it on. ## What DPoP protects, and what it doesn't {% table %} - Threat - Bearer token - DPoP --- - Token copied from a log or trace - Works for the attacker - Useless without the key --- - Token replayed to a different endpoint - Works - Rejected (`htu` binds method and path) --- - Traffic intercepted in transit (TLS stripped or terminated by an attacker) - Works indefinitely - Limited: the attacker captures the proof too, but it only works for that method and path, for the length of the acceptance window --- - Agent process fully compromised, key included - Works - Also works: this is the limit {% /table %} That last row is where DPoP stops. DPoP binds the token to a key. If an attacker compromises the agent process and takes the key along with the token, DPoP gives you nothing, because now they can sign proofs too. It protects against copied tokens, not against a fully compromised holder. Anyone pitching DPoP as protection against a rogue agent is overselling it. Two rows deserve a footnote. First, DPoP is not a replacement for TLS. RFC 9449 says it "MUST always be used in conjunction with HTTPS," and it leans on TLS for message integrity. An attacker who can read your traffic captures the proof along with the token; what DPoP buys you there is that the captured pair is scoped to one method and path and expires in seconds, instead of being a working credential until the token does. Second, note that `htu` covers the path, not the query string. A proof captured for one call isn't tied to the specific parameters of that call, only to the method and endpoint. ### The partial-compromise case, and what the nonce is for There's a case between "token leaked" and "key stolen." An attacker with brief code execution inside the agent can mint DPoP proofs dated well into the future, exfiltrate them alongside a token, and keep using the pair long after losing access. Nothing in the base mechanism stops this, because the proofs are genuinely signed by the right key. The fix is a server-issued nonce. The server hands the client an unpredictable value it must include in the proof, which means proofs can't be minted for a future the attacker can't see. If your threat model includes agents that might be transiently compromised, and for anything running third-party tool code it should, the nonce is the part that matters, not the signature. ## What it costs to run DPoP isn't free. The costs are real, and you should measure them before you enable it everywhere. **A signature on every request.** Each call adds a private-key signature on the client and a verification on the server. With ES256 or EdDSA that's small per call, but an agent making thousands of calls an hour multiplies it. Watch tail latency, not just the average, since the slow requests are what stall a workflow. **Replay protection needs state somewhere.** A proof has to be single-use within its window, and there are two ways to get there. Track recently seen `jti` values: simple, but the cache grows with request rate and has to be shared across every server instance or the protection has holes. Or keep the acceptance window short and have the server issue nonces, which bounds the state by nonce lifetime instead of by traffic. Either way there's shared state to operate; the second approach just makes it a fixed cost rather than one that scales with your busiest agent. **Clock skew.** Proofs carry a timestamp and are valid only briefly. If agent and server clocks drift apart, legitimate requests start failing. Choose the tolerance window on purpose rather than inheriting a default. **Where the key lives.** A private key in an environment variable is a private key in every crash dump and log line. The key's protection is the whole security of the scheme, so it deserves more care than the token ever did. ## Where the key should live The tempting default is one key per agent, held in the agent's own process. It's also the weakest, because compromising the process hands over the key. A stronger pattern holds signing keys at a trust boundary the agent calls into, rather than scattered inside every agent, and mints short-lived, sender-constrained tokens for each hop. A single compromised agent then can't walk away with a reusable key. Be clear-eyed about what moves when you do this: the DPoP proof now attests that the boundary holds the key, not that any particular agent does, so the agent-to-boundary hop needs its own authentication and its own identity claim. You're trading a possession proof about many processes for a possession proof about one service you can actually harden. Usually worth it, but it's a trade, not a free upgrade. If you're running many agents, build that boundary before you turn DPoP on across the fleet. ## DPoP is not delegation, and it's not identity This is where teams over-rely on it. DPoP proves exactly one thing: the caller holds the key the token is bound to. It says nothing about which user authorized the action, which agent is calling, or who's acting on whose behalf. Those are separate problems with separate answers: **Identity:** which agent is this? That needs an explicit agent identifier on the token, not a proof of key possession. **Delegation:** on whose behalf, and through what chain? That's RFC 8693 token exchange and actor claims, tracking who handed work to whom. DPoP sits underneath both. A complete agent-auth setup uses DPoP to stop token theft, an agent identity to say who's calling, and a delegation chain to say for whom. AuthPlane models these as separate layers for exactly this reason: DPoP for possession, an explicit `agent_id` for identity, and an RFC 8693 chain for delegation. ## When should you use DPoP for an MCP server? Turn it on when your MCP server is remote, when tokens pass through agent frameworks that log or fan them out, or when a leaked token would be a real incident rather than a shrug. Leave it off when you're local and single-agent behind TLS, with short-lived tokens and no logging exposure, because bearer is already enough there and DPoP would be cost without benefit. [AuthPlane](https://github.com/AuthPlane) supports DPoP (RFC 9449) for sender-constrained tokens, off by default, with a 60-second proof window and an optional server-issued nonce backed by a persisted store, so you can enable it where it earns its cost and leave it off where it doesn't. The point isn't to sign every request everywhere. It's to make a stolen token worthless in the places agents actually leak them. ## Sources *Primary and official sources, accessed August 2026.* - **RFC 9449**, OAuth 2.0 Demonstrating Proof of Possession (DPoP). Fett, Campbell, Bradley, Lodderstedt, Jones, Waite, September 2023. datatracker.ietf.org/doc/html/rfc9449 - **RFC 9700**, Best Current Practice for OAuth 2.0 Security. Lodderstedt, Bradley, Labunets, Fett, January 2025. datatracker.ietf.org/doc/html/rfc9700 - **RFC 8705**, OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens. Campbell, Bradley, Sakimura, Lodderstedt, February 2020. datatracker.ietf.org/doc/html/rfc8705 - **RFC 6750**, OAuth 2.0 Authorization Framework: Bearer Token Usage. Jones, Hardt, October 2012. datatracker.ietf.org/doc/html/rfc6750 - **RFC 7519**, JSON Web Token (JWT). Jones, Bradley, Sakimura, May 2015. datatracker.ietf.org/doc/html/rfc7519 - **A. Goswami**, Agentic JWT: A Secure Delegation Protocol for Autonomous AI Agents, arXiv:2509.13597, September 2025. arxiv.org/abs/2509.13597 --- # AuthPlane vs Keycloak for MCP Auth: MCP-Native vs the Identity Heavyweight - Published: 2026-08-19 - Tag: COMPARISON - URL: https://authplane.ai/blog/authplane-vs-keycloak/ - Excerpt: Keycloak's RFC 8707 support is experimental and undocumented for MCP; its MCP guide still prescribes manual audience mapping. AuthPlane does it by default. A source-verified comparison of two self-hosted options. *Two open-source, self-hosted options for securing an MCP server. One is a full identity platform that recently learned MCP. The other was built for it. Where they actually differ.* ## TL;DR Keycloak and AuthPlane are the two that share a quadrant: open source and self-hosted. The split is a general-purpose identity platform versus a server built only for MCP. The gap that decides most evaluations: Keycloak's Resource Indicators support is experimental and its MCP guide doesn't use it, so the documented path is binding audiences by hand with a per-scope mapper. AuthPlane does it by default. Keycloak if you already run it and want one platform for human identity plus MCP. AuthPlane if MCP authorization is the job and you want it agent-aware and small. If you're comparing self-hosted ways to put OAuth in front of an MCP server, the shortlist is short, and Keycloak is on it. It's the mature, widely deployed, open-source identity platform, and it now has a real MCP guide. So this isn't the usual story of a heavyweight that hasn't noticed MCP. It's a closer call, and it comes down to a few specific differences. ## Is Keycloak a good MCP authorization server? It can be, with one real caveat. Keycloak is a Cloud Native Computing Foundation project, Apache-2.0, with a decade of production behind it as an identity provider for human login, SSO, and federation. Its MCP support is recent but moving fast: the dedicated MCP guide arrived in Keycloak 26.5 (January 2026), experimental Client ID Metadata Document (CIMD) support in 26.6 (April 2026), and experimental token-exchange delegation plus documented Claude Code and VS Code integration in 26.7 (July 2026). The caveat is Resource Indicators, and it's the next section, because it's what most often shapes the decision. The answer there is more interesting than a flat yes or no. Everything else about Keycloak's OAuth core is solid: OAuth 2.1, RFC 8414 metadata, Dynamic Client Registration, and CIMD behind an experimental flag (`bin/kc.sh start --features=cimd`). If Keycloak is already in your stack, extending it to MCP is a reasonable afternoon. If it isn't, you'd be adopting a broad identity platform to solve a narrower problem. ## Does Keycloak support RFC 8707 Resource Indicators? Yes, but with three caveats that matter more than the headline. This is the one place where reading Keycloak's guide will mislead you, so read this part slowly. Keycloak has shipped a Resource Indicators implementation since 26.6 (April 2026). It reads the `resource` parameter, validates it, enforces that the value on the token request matches the authorization request, and sets the access token's audience accordingly. If you enable it, Keycloak does bind audiences from `resource`. The catch is in how you enable it and whether the MCP path uses it. - **It's experimental.** The feature is flagged EXPERIMENTAL in Keycloak's own feature registry, so it's off by default. You opt in with `--features=resource-indicators`, and Keycloak reserves the right to change it in a breaking way. - **Keycloak's MCP guide doesn't use it.** The guide still lists RFC 8707 as "Not supported," still states that Keycloak can't recognize the `resource` parameter, and still walks you through the manual workaround. If you follow the official MCP integration guide, you'll build the mapper setup, because that's what it tells you to do. - **It's modelled around clients, not MCP resources.** The `resource` has to resolve to a registered client, either as `urn:client:` or by giving a client a `resource_url` attribute that matches. Keycloak's own guide hints at the gap when it says the community is still working to process `resource` "as the MCP specification expects." So there's still per-server setup, just one client attribute rather than a mapper per scope. The documented Keycloak path is still manual. For a server at `https://example.com/mcp` with three scopes, you create a client scope for each and add an Audience mapper to each with the server URL in the Included Custom Audience field. Three scopes, three mappers, one server. Add another server and you repeat it. AuthPlane does this by default, with no feature flag and no client mapping. Register the MCP server once, and a token issued for that server is audience-bound to its exact URI. If you're running one MCP server and don't mind the setup, either path works. If you're running several, or you'd rather not depend on an experimental flag, this is the line item that tends to decide it. ## What is AuthPlane, and how is it different? AuthPlane is an open-source OAuth 2.1 authorization server built specifically for MCP. The server is AGPL-3.0, the SDKs are Apache-2.0. It ships as a single Go binary with an embedded admin UI and runs alongside your MCP server, validating tokens locally against the JWKS so nothing sits in your request path. The two differ in shape more than in quality. Keycloak is a general identity platform that added an MCP guide. AuthPlane is an MCP authorization server, so what would be features buried inside a larger system for Keycloak (audience binding, agent identity, protected-resource metadata, MCP SDK integration) are its entire job. On audience binding specifically, AuthPlane reads the `resource` parameter and stamps that exact URI into the token's audience whenever a grant targets a registered resource, matching on scheme, host, port, path, and trailing slash, with one audience per token. When a grant supplies no resource, the audience falls back to the issuer. The cost of that focus is maturity: AuthPlane is a v0.2.0 project from a new org, and its docs don't pretend otherwise. ## Agent identity and delegation Keycloak has no MCP-specific agent identity model. It supports standard OAuth token exchange, and 26.7 added an experimental token-exchange delegation feature: a delegation scope that checks whether the requesting user is authorized to act on behalf of a target user. That's useful, and it's early. What it isn't is a first-class agent object with a stable identifier. AuthPlane models this directly. Tokens issued to a client registered as an agent carry an explicit `agent_id` and a delegation chain built on the RFC 8693 `act` claim, so a downstream MCP server can read the current actor without walking a nested tree. Non-agent traffic (service-to-service, admin) is issued without those claims, so your server can tell the two apart. One caveat applies to any product here: RFC 8693 treats the nested actors in a chain as informational, not as an enforced access-control path, and AuthPlane's chain nests up to five hops with an eight-entry flattened claim. So the value is attribution and audit, not a cryptographically enforced full chain. ## Spec currency: where both actually stand They land close here, and the precise version keeps anyone from overclaiming. Keycloak's guide currently reports "Partially Supported" for MCP 2025-11-25, the partial being RFC 8707, which its guide doesn't use even though the code ships it experimentally. AuthPlane targeted 2025-11-25 as well when this was written, with audience binding on by default. *Update, September 2026:* both have since moved to the 2026-07-28 revision. AuthPlane v0.2.0 implements it end to end — Client ID Metadata Documents on by default, RFC 9207 `iss`, Protected Resource Metadata served by the AS, and RFC 8707 audience binding on by default. Keycloak's guide now lists 2026-07-28 as "Partially Supported without Resource Indicators for OAuth 2.0" — the same partial as before, carried forward. So the version gap closed, and the difference is still how each handles RFC 8707. ## Operational surface: a platform vs a binary Keycloak gives you a lot: realms, user stores, federation, clustering, authorization services, and broad protocol support, all valuable when human identity is part of the job. It's also a JVM platform with the configuration and operational footprint that implies. AuthPlane gives you one Go binary with an embedded admin UI and a narrow MCP scope. If you need the identity platform, Keycloak's breadth is a genuine advantage. If MCP authorization is the whole job, that breadth is surface you operate without using. ## AuthPlane vs Keycloak, side by side Keycloak cells are verified against its source code at the 26.7.1 tag, not only its guide, since the two disagree on Resource Indicators. {% table %} - Dimension - AuthPlane - Keycloak --- - Hosting - Self-hosted, single Go binary - Self-hosted, JVM identity platform --- - License - AGPL-3.0 server, Apache-2.0 SDKs - Apache-2.0 --- - Built for - MCP authorization and agent delegation - General identity (SSO, federation); MCP added recently --- - MCP support - Implements the 2026-07-28 spec (v0.2.0) - MCP guide since 26.5; guide reports 2026-07-28 partial (without Resource Indicators); CIMD and Resource Indicators experimental --- - Resource Indicators (RFC 8707) - Supported by default, automatic audience binding - Experimental since 26.6 (off by default); MCP guide still documents the scope + Audience mapper workaround --- - Agent identity - Explicit `agent_id` + RFC 8693 chain on agent tokens - No MCP agent model; experimental token-exchange delegation (26.7) --- - Operational surface - Single binary, embedded admin UI - Realms, user stores, federation, clustering, policies --- - Maturity - Early, v0.2.0, new org - Mature, widely deployed, CNCF project {% /table %} ## When is Keycloak the right call? Keycloak is the better choice when identity is bigger than MCP for you. Specifically: - You already run Keycloak and have the operational expertise in house. - You need a full human-identity platform, with SSO, federation, and user management, and MCP is one use case inside it. - You can live with the manual mapper workaround the MCP guide documents (or with enabling the experimental Resource Indicators flag), plus the experimental status of CIMD and token-exchange delegation. - You want a long-established, broadly deployed open-source platform behind your auth. ## When is AuthPlane the right call? AuthPlane is the better choice when MCP authorization is the job and you want it agent-aware and small: - You want an MCP-focused authorization server without operating a full identity platform. - You want RFC 8707 audience binding on by default, not behind an experimental flag or per-server mappers. - You want an explicit `agent_id` and delegation chain represented in the tokens. - You want a single binary with an embedded admin UI and a small configuration surface. Both are open source and self-hosted, which makes this the cleanest head-to-head in the field: stand each one up against a staging MCP server for an afternoon and see which answers your requirements. If Keycloak's already in your stack, extending it can win on effort alone. If it isn't, and MCP is the job you're solving, AuthPlane is built for it. ## Frequently asked questions **Does Keycloak support RFC 8707 Resource Indicators for MCP?** Partly. Keycloak has shipped an experimental Resource Indicators feature since 26.6 (April 2026) that reads the `resource` parameter and binds the token audience from it, enabled with `--features=resource-indicators`. But it's off by default, subject to breaking changes, and requires the resource to map to a registered client. Keycloak's own MCP guide doesn't use it. The guide still lists RFC 8707 as "Not supported" and documents a manual workaround with a per-scope Audience mapper instead. AuthPlane supports RFC 8707 by default and binds the audience to the registered resource URI automatically. **Is Keycloak a good MCP authorization server?** It can be, especially if you already run it. Keycloak added a dedicated MCP guide in 26.5, experimental CIMD in 26.6, and experimental token-exchange delegation in 26.7. The main caveat is that its guide reports only partial support — for 2025-11-25 and now 2026-07-28 alike — because it doesn't use the experimental Resource Indicators feature the code now ships. **Are AuthPlane and Keycloak both open source and self-hosted?** Yes. Keycloak is Apache-2.0. AuthPlane's server is AGPL-3.0 with Apache-2.0 SDKs. Both run inside your own environment. The difference is general-purpose identity versus a purpose-built MCP authorization server. **Does Keycloak support agent identity and delegation?** Keycloak supports standard OAuth token exchange and, in 26.7, an experimental token-exchange delegation feature that checks whether a user is authorized to act on behalf of another. It doesn't document a dedicated MCP agent identity model like AuthPlane's `agent_id` and actor-chain claims. **Is AuthPlane lighter to run than Keycloak?** In footprint, yes. AuthPlane is a single Go binary with an embedded admin UI and a narrow MCP scope. Keycloak is a full JVM identity platform with far more functionality and a correspondingly larger configuration and operational surface. Lighter isn't automatically better: if you need the platform, its breadth is why you're there. ## Sources *Primary sources and source code, accessed August 2026. Keycloak claims verified against the 26.7.1 release tag, not documentation alone.* - Keycloak, [Integrating with Model Context Protocol (MCP)](https://www.keycloak.org/securing-apps/mcp-authz-server): conformance table, CIMD flag, and the mapper workaround; note this guide still lists RFC 8707 as "Not supported." - Keycloak source, [Profile.java at tag 26.7.1](https://raw.githubusercontent.com/keycloak/keycloak/26.7.1/common/src/main/java/org/keycloak/common/Profile.java): `RESOURCE_INDICATORS` feature, flagged experimental. - Keycloak, [26.5.0 released](https://www.keycloak.org/2026/01/keycloak-2650-released) (Jan 2026): dedicated MCP integration guide. - Keycloak, [26.6.0 released](https://www.keycloak.org/2026/04/keycloak-2660-released) (Apr 2026): experimental CIMD support. - Keycloak, [26.7.0 released](https://www.keycloak.org/2026/07/keycloak-2670-released) (Jul 2026): experimental token-exchange delegation; Claude Code and VS Code integration. - Model Context Protocol, [Authorization specification, 2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization) (current). - IETF, [RFC 8707, Resource Indicators for OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc8707). - IETF, [RFC 8693, OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693). *Last updated: September 15, 2026 — spec-version rows reflect AuthPlane v0.2.0 and Keycloak's current guide. The MCP auth landscape moves fast. Keycloak's Resource Indicators feature may graduate from experimental and its MCP guide may be updated; verify feature flags and version numbers against vendor sources.* --- # API keys or OAuth for your MCP server - Published: 2026-08-13 - Tag: EDUCATION - URL: https://authplane.ai/blog/mcp-api-keys-vs-oauth/ - Excerpt: When a static API key is fine for an MCP server, the four things it can't do, and what the MCP spec actually recommends once you go remote. *When a static key is fine, the exact point where it stops being fine, and what the spec wants once you cross it.* ## TL;DR - A static API key is fine for a local, single-user MCP server that nothing else can reach. The spec even endorses it for STDIO servers. - Go remote and the spec expects OAuth 2.1 (a SHOULD, not a MUST). Add a second agent or move near regulated data and the four gaps below turn real on their own, whatever the spec says. - The move off a key is a middleware swap, not a rewrite. You've got a key in a `.env` file and someone just told you that's a problem. Maybe it is. Maybe it isn't. You're in good company either way: when Astrix Security analyzed more than 5,200 open-source MCP servers for its [State of MCP Server Security 2025](https://astrix.security/learn/blog/state-of-mcp-server-security-2025/) report, published that October, 53% were running on long-lived static keys or personal access tokens and only 8.5% used OAuth. The study read repository READMEs rather than code, so treat the split as directional. This is about the exact line where a key stops being fine, so you can check which side of it you're on instead of taking anyone's word for it. ## When an API key is fine for an MCP server Local server. One user. One agent. No agent handing work to another. Nothing regulated. Not reachable from the internet. Tick all of those and a static key is a reasonable call, and most of OAuth would be machinery you never touch. That's not a setup for a gotcha. It's true, and it's why the next part lands: the problems with keys are real, but they're conditional, and the condition is the moment you step outside that box. ## Four things an API key can't do that OAuth can Once your server is shared, remote, multi-agent, or near regulated data, a key hits four walls. None are fixable while it stays a key. ### It never expires on its own A leaked key is good until a human notices and rotates it, which might be never. An OAuth access token ages out on a timer you set, typically minutes, so a leak has a bounded blast radius instead of a door left open for months. ### It can't scope down There's one key, so the agent that reads your issues carries the same credential as the one that can delete the repo. OAuth scopes let you hand each agent only what it needs, and a compromised reader stays a reader. ### It carries no identity A key proves someone holds the key. It can't tell your server which user is behind a call, or which agent is acting for whom. Row-level security, per-user limits, tenant isolation: all of it needs an identity the key doesn't carry. ### It can't recover Revoke a key and the agent has nothing to fall back on. Calls start returning 401 mid-workflow, and the agent has no way to ask for a new credential, someone has to notice and hand it one. OAuth clients handle this themselves: the refresh flow lets a client get a fresh token without human intervention, and when rotation is enabled a replayed refresh token is a signal you can alert on rather than a silent reuse. ## Does the MCP spec require OAuth? Less than people assume, and the honest answer is more useful than the scary one. The spec says authorization is OPTIONAL. For STDIO servers it goes further: implementations SHOULD NOT follow the authorization spec at all, and should take credentials from the environment instead, which is the spec explicitly endorsing the key in your `.env` for local servers. For HTTP transports it says implementations SHOULD conform to the authorization spec, and that spec is built on OAuth 2.1 with PKCE. SHOULD is not MUST: you can deviate if you have a reason and understand what you're giving up. So a static key on a remote server isn't a spec violation. It's a documented deviation from what the spec recommends, and the thing you give up is bigger than compliance. MCP clients discover how to authenticate through Protected Resource Metadata and the `WWW-Authenticate` challenge. A static key takes part in none of that. Any agent that isn't yours can't connect without you provisioning a secret out of band, one client at a time. That's what usually forces the move, well before anyone raises the spec. The 2026-07-28 revision tightened the model around OAuth rather than the requirement to use it: issuer validation under RFC 9207, client credentials bound to the server that issued them, and Dynamic Client Registration formally deprecated in favor of Client ID Metadata Documents. See the [authorization section of the spec](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization). ## How to migrate from API keys to OAuth Moving from an API key to OAuth is a smaller code change than it sounds. Right now your server checks one thing on each request: does it carry the correct secret key? With OAuth it checks a token instead: is the token valid, was it issued for this server, and does it grant the permission this call needs? That check runs in the same place it does today, the middleware that sits in front of your request handlers. You're changing what gets verified, not how requests move through your server. **Before:** `if request.header("x-api-key") != API_KEY: reject()` **After:** the SDK fetches your authorization server's JWKS, verifies the token's signature, checks the audience and required scope, and hands your handler the identity. The AuthPlane SDKs for Go, TypeScript, Python, Java, and C# do this behind one call, and also serve the Protected Resource Metadata endpoint your clients use to discover where to authenticate. ## API keys vs OAuth: a side-by-side comparison The middle column is roughly what you get from an OAuth 2.1 server. The right column is what AuthPlane adds on top. {% table %} - Capability - Static API key - OAuth 2.1 (any compliant server) - With AuthPlane --- - Expiry - Never, until rotated by hand - Short-lived access tokens - Short-lived, configurable --- - Scoping - All or nothing - Per-scope, as granular as you define - Per agent, per tool --- - Identity - Holder only - End user (`sub`) and client - Plus agent identity and delegation chain on agent-mediated calls --- - Revocation - Silent 401s, no recovery - Revocation endpoint and refresh flow - Refresh rotation with replay detection and family revocation --- - Audit trail - None - Whatever your AS records - Issuance and consent logged by default --- - Remote MCP, spec-aligned - Deviates from the spec's SHOULD - Yes - Yes {% /table %} ## API keys or OAuth: which should you use? Keep the key if you're local and solo. The day you go remote, the spec's recommendation and your clients' discovery flow both point the same way. Add a second agent or get near regulated data and those four gaps turn real regardless. The move is a middleware swap, not a rewrite. If you want SDKs that handle the validation end for you, they're here: [github.com/AuthPlane](https://github.com/AuthPlane). ## Sources *Primary and official sources, accessed August 2026.* - **MCP Authorization specification**, 2026-07-28 (current). modelcontextprotocol.io/specification/2026-07-28/basic/authorization - **Astrix Security**, State of MCP Server Security 2025 (published October 2025). astrix.security/learn/blog/state-of-mcp-server-security-2025 - **RFC 7636**, Proof Key for Code Exchange (PKCE). datatracker.ietf.org/doc/html/rfc7636 --- # AuthPlane vs Auth0: Self-Hosted MCP Auth vs the Managed Incumbent - Published: 2026-08-06 - Tag: COMPARISON - URL: https://authplane.ai/blog/authplane-vs-auth0/ - Excerpt: Auth0's Auth for MCP reached GA in May 2026. AuthPlane is the self-hosted, open-source alternative. A fair comparison on hosting, agent identity, and data residency. *Part of our field guide to MCP server authentication.* Your MCP server works. The demo went fine, the team is already routing real tool calls through it, and then someone in standup asks the question that always shows up two weeks late: who's actually allowed to call this thing, and can we prove it after the fact? That's usually the moment a team starts shopping for an authorization layer, and for most of them it comes down to two options: the identity platform they already pay for, or a newer tool built specifically for MCP. Here's how AuthPlane and Auth0 actually compare once you get past the landing pages. ## TL;DR Auth0 and AuthPlane both provide an OAuth authorization layer for MCP. The difference is where it runs and how each product models agent identity and delegation. Auth0 is the managed incumbent. Its Auth for MCP product reached general availability in May 2026, it integrates with the Okta identity platform, and it's the lowest-effort choice if you already live in that ecosystem and can use a vendor-managed cloud. AuthPlane is the self-hosted, open-source option. It runs inside your own infrastructure, provides an explicit `agent_id` model and RFC 8693 actor-chain claims, and fits teams that need direct operational control over the authorization server, signing keys, token records, and vaulted credentials. It's also intentionally narrow and still early (v0.2.0), with a managed cloud offering in the works but not yet available. Short version: if you already use Auth0 or Okta and a managed service fits your requirements, Auth0 is the practical call. If you need to operate the authorization layer yourself, or explicit MCP-focused agent identity is a first-class need, AuthPlane is built for that case. ## What is Auth0's MCP offering? Auth0 is one of the most established identity platforms on the market, owned by Okta since 2021. Its Auth for MCP product became generally available on May 6, 2026, after a run in early access that started the previous November. If Auth0 is already part of your identity stack, this is the section worth reading closely. On the MCP side, Auth for MCP covers the parts of the authorization model that matter for production: - OAuth 2.1 security practices and OpenID Connect, with Universal Login handling the user sign-in step. - Client ID Metadata Documents (CIMD) for URL-based client registration, alongside pre-registration and Dynamic Client Registration where those approaches fit. - On-Behalf-Of token exchange under RFC 8693, preserving the original user in `sub` and recording participating services in nested `act` claims. - A Resource Parameter Compatibility Profile for MCP resource identifiers and RFC 8707-style audience binding. - Token Vault for storing and refreshing third-party tokens, with pre-built connections to Google, GitHub, Microsoft, Slack, and 30-plus other providers. - Auth0 Fine-Grained Authorization (FGA), a separate relationship-based authorization service that can treat agents as first-class principals for resource- and tool-level permission decisions. It's designed for standards-compliant MCP clients and common agent environments. Actual compatibility still depends on the client's registration method, redirect behavior, and support for the relevant MCP authorization flow. ## Where do AuthPlane and Auth0 overlap? Both cover the standards floor expected in current MCP authorization deployments: PKCE-protected OAuth flows, resource- or audience-bound access tokens, authorization-server discovery, scoped access, token exchange, and federation to an upstream identity provider. The spec itself has been moving fast. The 2025-11-25 release is what most production MCP deployments were built against. Then, on July 28, 2026, after months as a release candidate, the working group shipped 2026-07-28: a larger revision that drops the stateful handshake in favor of a stateless protocol core, formally deprecates Dynamic Client Registration in favor of CIMD, and adds RFC 9207 issuer validation. AuthPlane v0.2.0 (September 2026) implements the 2026-07-28 revision end to end and publishes a compliance statement for it. Auth0's CIMD support already lines up with where the new spec landed, though its docs haven't yet published a full 2026-07-28 compliance statement; the comparison below reflects what's documented today. If your only question is whether you can place a standards-based OAuth layer in front of an MCP server, both answer yes. The decision lives in the differences below, not the overlap. ## How do AuthPlane and Auth0 actually differ? This is where the two-horse race actually splits. Three differences decide most evaluations: hosting model, product scope, and how each one represents agent identity. {% table %} - Dimension - AuthPlane - Auth0 (Okta) --- - Hosting - Independently self-hosted in your infrastructure - Public or private vendor-managed cloud --- - License - AGPL-3.0 server; Apache-2.0 SDKs - Proprietary --- - Built for - MCP authorization and agent delegation - Broad human identity platform with MCP and AI-agent capabilities --- - MCP support - Implements MCP Authorization spec 2026-07-28 end to end (v0.2.0) - Auth for MCP, GA May 2026; CIMD and resource-parameter compatibility --- - Agent identity - Explicit `agent_id` plus RFC 8693 actor-chain claims - OBO preserves the user and nested `act` chain; Token Vault and optional FGA --- - Token data path - Authorization server, keys, token records, and vault stay under your infrastructure control - Token issuance runs in Auth0 public or private managed cloud --- - Maturity - Early (v0.2.0), narrow focus, not SOC 2 certified (self-hosted means the certification is yours) - Established platform and enterprise footprint --- - Best when - You need self-operated, open-source, MCP-focused auth - You already run Auth0 or Okta and prefer a managed platform {% /table %} **Hosting and data residency.** This is usually the first filter. Auth0 offers multi-tenant Public Cloud and dedicated Private Cloud deployments on AWS and Azure, but both are managed services with weekly automatic updates. AuthPlane is software you deploy and operate inside your own boundary, as a single Go binary today (a managed cloud version is on AuthPlane's roadmap, but it isn't available yet, so self-hosting is currently the only way to run it). For teams with on-prem, air-gapped, or direct operator-control requirements, that difference tends to be decisive. **MCP-focused identity, or broader platform identity.** Auth0 preserves complete service-delegation chains through nested `act` claims in its OBO flow, and its optional FGA layer lets you model agents as first-class principals with relationship-based rules. AuthPlane differentiates with an explicit `agent_id` and `agent_chain` model built directly on top of the same RFC 8693 `act` claim, so a downstream MCP server can gate on the current actor without walking a nested tree by hand. The distinction isn't whether Auth0 supports delegation; it does. The distinction is product model and operational scope: AuthPlane's extension exists purely to make agent-aware authorization decisions cheap inside an MCP tool handler. **Platform breadth, or focused scope.** Auth0 brings years of enterprise hardening, SSO and directory tooling, a broad set of authentication features, and a large support organization. AuthPlane is at v0.2.0 and deliberately narrow, and it says so plainly in its own docs: it's validated against Claude Desktop, Claude Code, and MCP Inspector, with Cursor and VS Code support still tracked separately, and it isn't SOC 2 certified because self-hosted software makes that certification yours to earn. If you need a broad identity platform for humans and agents across a large organization, Auth0's maturity is a real advantage. ## When is Auth0 the right call? - You already run Auth0 or Okta, and extending that platform to MCP is the path of least resistance. - Your identity and token issuance requirements can be met by a vendor-managed public or private cloud. - You want one platform covering human SSO, directories, agent auth, and enterprise support. - You value a long production track record and managed operations over independently running the authorization server. ## When is AuthPlane the right call? - You need to deploy and operate the authorization server inside your own environment. - You want signing keys, token records, and vaulted credentials to remain under your infrastructure control. - Explicit agent identity and delegation chains are a first-class need in the token model. - You want source-auditable auth you can run and fork yourself (AGPL-3.0 server, Apache-2.0 SDKs). - You're comfortable running a focused, early-stage tool in exchange for full operational control of the auth layer. AuthPlane is open source, so the honest way to decide is to point it at your own MCP server for an afternoon and compare it with Auth0 on the requirements that actually matter to you. That's the same test the team from the top of this article should run: stand up AuthPlane against a staging server, see if it answers the question that started the whole evaluation, and then decide whether a managed platform is worth the trade-off. If Auth0 fits better, use Auth0. ## Frequently asked questions **Is Auth0 open source?** No. Auth0 is a proprietary platform delivered through managed cloud deployments. AuthPlane is open source, with the server under AGPL-3.0 and the SDKs under Apache-2.0. **Can I self-host Auth0 for MCP?** Not in the sense of installing and independently operating the Auth0 authorization server. Auth0 offers dedicated Private Cloud deployments on AWS and Azure, but its own documentation describes them as managed services, complete with scheduled updates Auth0 controls. **Does Auth0 support agent identity and delegation?** Yes. Auth0 OBO token exchange preserves the original user and records the service chain in nested `act` claims. Token Vault supports third-party credentials across 30-plus providers, and Auth0 FGA can add relationship-based authorization that treats agents as principals. AuthPlane adds an explicit `agent_id` and `agent_chain` model on top of the same RFC 8693 mechanics and packages it in a narrower, MCP-focused server. **When did Auth0 support MCP?** Auth for MCP reached general availability on May 6, 2026. AuthPlane v0.2.0 implements the MCP Authorization specification dated 2026-07-28 — a revision published after this article's original publication. Auth0's public documentation has not yet published a full 2026-07-28 compliance statement. ## Sources *Primary and vendor sources, accessed August 6, 2026.* - Auth0, [Auth for MCP Is Now Generally Available](https://auth0.com/blog/auth0-auth-for-mcp-servers-generally-available/): GA date, CIMD, OBO token exchange, and MCP resource support. - Auth0 Docs, On-Behalf-Of Token Exchange: `sub` preservation, nested `act` claims, and delegation-chain limits. - Auth0 Docs, Register Applications with CIMD: CIMD requirements and MCP resource-parameter guidance. - Auth0, [Token Vault](https://auth0.com/features/token-vault): supported third-party credential storage and exchange, 30-plus providers. - Auth0 Docs, Private Cloud Deployments (AWS and Azure): private-cloud options are dedicated managed services, weekly automatic updates. - Auth0, [Fine-Grained Authorization](https://auth0.com/fine-grained-authorization): relationship-based authorization for apps, APIs, MCP servers, and agents. - Model Context Protocol, [The 2026-07-28 Specification](https://blog.modelcontextprotocol.io/posts/2026-07-28/): final release date, release-candidate lock date of May 21, 2026, and what changed from 2025-11-25. - AuthPlane, [compliance statement](https://github.com/AuthPlane/authserver/blob/main/docs/reference/compliance.md): 2026-07-28 MCP Authorization spec coverage. AuthPlane Docs, [RFC compliance](https://docs.authplane.ai/reference/rfc-compliance/): RFC-by-RFC support table. - AuthPlane Docs, [Agent identity](https://docs.authplane.ai/concepts/agent-identity/) and [Delegation & act-chain](https://docs.authplane.ai/concepts/delegation-act-chain/): `agent_id`/`agent_chain` claims and RFC 8693 mechanics. - AuthPlane, [authserver and SDK repositories](https://github.com/authplane): current open-source product capabilities, v0.2.0 status, and licensing (AGPL-3.0 server, Apache-2.0 SDKs). *Last updated: September 15, 2026 — AuthPlane rows reflect v0.2.0 (MCP Authorization 2026-07-28). The MCP auth landscape moves fast. Verify GA dates, feature status, and version numbers against vendor documentation before publishing.* --- # The MCP auth production checklist - Published: 2026-07-31 - Tag: SECURITY - URL: https://authplane.ai/blog/mcp-auth-production-checklist/ - Excerpt: An eight-point production checklist for MCP server authorization: discovery, tokens, scopes, refresh, key rotation, identity, audit, and client registration, each with a pass test. *Eight things to verify before you put an authenticated MCP server in production. Each one has a test, so you can prove it rather than assume it.* ## TL;DR - This is a vendor-neutral pre-flight list. Every item is something you should verify regardless of what authorization server you run. - Each check is written as: what to verify, why it matters, and how you know you passed. If you cannot describe the passing test, treat the item as failing. - The eight areas: discovery, tokens, scopes, refresh and revocation, key rotation, identity, audit, and client registration. Getting an MCP server to authenticate at all is the easy 80%. The last 20%, the part that survives a security review, is a set of specific behaviors that are easy to skip and hard to add back later. This checklist is that 20%. It is deliberately not AuthPlane-specific: work through it against whatever you run. We only appear at the end, as one way to satisfy the list. Context for why this matters: Astrix Security's [State of MCP Server Security 2025](https://astrix.security/learn/blog/state-of-mcp-server-security-2025/) found that of 5,200+ MCP servers analyzed, only 8.5% used OAuth and more than half relied on long-lived static keys. Most servers would fail item two below on the first try. ## 1. Discovery Your MCP server must publish Protected Resource Metadata (RFC 9728) at the exact well-known path, and the authorization server it points to must be reachable and expose its own metadata. Clients rely on this to find where to authenticate without manual configuration. **Pass test:** MCP Inspector completes discovery against your server with no hand-entered endpoints. It reads the 401, follows the `resource_metadata` pointer, finds the authorization server, and proceeds. ## 2. Tokens Tokens must be audience-bound to your server's identifier, and their lifetime must be a deliberate choice rather than a library default. Audience binding is what stops a token minted for one MCP server from working against another. **Pass test:** present a token whose audience is a different server. Your server rejects it. And you can state your token lifetime and the reason you chose it. ## 3. Scopes Scopes should be enforced per tool, not per server. "This agent can reach this server" is not access control. "This agent can call `read_db` but not `write_db`" is. Blanket access is the difference between a compromised agent that can read and one that can delete. **Pass test:** a token scoped for a read-only tool is refused when it calls a write tool, and the refusal happens at the server, not by convention. ## 4. Refresh and revocation Refresh tokens should rotate on every use, and a replayed (already-used) refresh token should revoke the entire token family. This turns a token theft into a detectable event: the moment the stolen token is replayed, the family dies and the legitimate client is forced to re-authenticate, which is your signal. **Pass test:** replay a rotated refresh token and confirm the family is revoked. You can point to the log entry where the replay was caught. ## 5. Key rotation Signing-key rotation must be non-breaking. Your JWKS endpoint should serve both the current and the previous key during the rotation window, so tokens signed just before a rotation still validate just after it. A rotation that invalidates in-flight tokens is an outage waiting for a deploy. **Pass test:** rotate keys in staging under live traffic. No request returns a 401 as a result of the rotation. ## 6. Identity Every call should be attributable to both a user and an agent. When an agent acts on a user's behalf, and especially when one agent delegates to another, the token should carry that chain. Without it, row-level security, per-user rate limits, and multi-tenant isolation are all impossible, because the server literally does not know who is calling. **Pass test:** from the audit log alone, you can answer "which agent made this call, on whose behalf, through which delegation chain" without guessing. ## 7. Audit Token issuance, consent decisions, delegation hops, and revocations should all be logged and queryable, with a retention setting you chose deliberately. This is the artifact SOC 2 and HIPAA reviews actually ask for, and the thing you will wish you had the first time an agent does something it should not have. **Pass test:** you can produce the full trail for a given token, from issuance to revocation, without shipping a code change to do it. ## 8. Client registration You should have chosen deliberately between pre-registration, Client ID Metadata Documents (CIMD), and Dynamic Client Registration (DCR), and be able to say why. As of the 2026-07-28 spec, DCR is formally deprecated in favor of CIMD. It still works for backward compatibility and will be removed in a future version, so new deployments should treat the real choice as pre-registration when your clients have a prior relationship with your server, and CIMD when they do not. The right answer depends on that relationship. **Pass test:** you can state, in one sentence, which registration approach you use and why, and if you still rely on DCR, that you know it is deprecated and have a path off it. "Whatever the library defaulted to" is a failing answer. ## How AuthPlane maps to the list AuthPlane is one way to satisfy these eight items without assembling them yourself. It issues audience-bound, short-lived tokens with tool-level scopes, rotates refresh tokens with family revocation on replay, serves current-plus-previous keys through rotation, carries agent identity and the delegation chain in every token, and writes issuance, consent, delegation, and revocation to a queryable audit log. It is validated against MCP Inspector with an automated end-to-end suite. Whether you use it or not, the checklist stands on its own. ## The bottom line If you can run every pass test above and point to the evidence, your MCP server is genuinely production-ready on the auth side. If any item is "we think so" rather than "here is the test that proves it," that is the item to fix first. Grab a runnable authorization server that clears the list out of the box: [github.com/AuthPlane](https://github.com/AuthPlane). ## Sources 1. MCP Authorization specification, 2026-07-28 (current version). 2. Model Context Protocol, The 2026-07-28 Specification (release announcement, DCR deprecation). 3. RFC 9728, OAuth 2.0 Protected Resource Metadata. 4. RFC 8707, Resource Indicators for OAuth 2.0. 5. Astrix Security, State of MCP Server Security 2025. --- # Authorization server or gateway: where MCP auth belongs - Published: 2026-07-30 - Tag: COMPARISON - URL: https://authplane.ai/blog/mcp-auth-without-gateway/ - Excerpt: Authorization server or gateway for MCP auth? A clear, vendor-neutral breakdown of the two patterns, what each costs, and why most production setups need both. *Two patterns get called "MCP auth," and they are not the same thing. A plain-language guide to which one you actually need.* ## TL;DR - An authorization server issues and signs tokens. A gateway sits in the request path and inspects traffic. They solve different problems. - MCP auth does not require a gateway. The spec's model is a resource server validating tokens it was handed, with token issuance handled separately. - A gateway adds an enforcement point and traffic visibility, at the cost of an extra hop and a component in your data path. - Most production setups end up wanting both, because a gateway with no authorization server behind it is enforcing a decision nobody actually made. "How do I add auth to my MCP server?" quietly contains two different questions, and mixing them up is the source of a lot of confusion when teams evaluate options. One question is about identity and consent: who is this agent, what is it allowed to do, and who granted that. The other is about traffic: what flows through my perimeter and where do I enforce policy on it. An authorization server answers the first. A gateway answers the second. This piece is about telling them apart and deciding what you need. ## The gateway pattern A gateway sits in front of your MCP server, on the request path. Every call passes through it, which is precisely what makes it useful. It gives you a single enforcement point, visibility into the traffic, policy at the edge, and rate limiting in one place. If you already run an API gateway for the rest of your services, routing MCP traffic through it is a natural instinct. The cost is structural. A gateway is an extra hop on every call, which means added latency and a component that has to be highly available because it is now in the critical path. It also means your MCP traffic passes through something that has to be trusted to see it. None of this makes gateways wrong. They are a legitimate, widely used pattern. It does mean you are accepting a real trade in exchange for edge control. ![Diagram of the gateway pattern: the client's MCP calls pass through a gateway on the request path before reaching the MCP server.](/media/blog/mcp-auth-gateway-pattern.svg) *Gateway pattern: every MCP call passes through the gateway, which enforces policy at the edge — at the cost of an extra hop and a component that sits in the data path and sees all traffic.* ## The authorization server pattern An authorization server does not sit in the request path. It issues a signed token to the client through the OAuth flow, and then steps out of the way. Your MCP server validates that token locally against the authorization server's public keys (its JWKS), with no call back to the authorization server on each request. Only the OAuth flows themselves, the initial authorize and token exchange, actually touch the authorization server. The practical effect is that there is no extra hop on your data path. The authorization server can be busy or briefly unavailable and your MCP server keeps validating tokens, because validation is a local cryptographic check, not a network round trip. ![Diagram of the authorization server pattern: the authorization server issues a signed token during the OAuth flow, then the client's MCP traffic goes directly to the MCP server, which validates the token locally against the JWKS.](/media/blog/mcp-auth-as-pattern.svg) *Authorization server pattern: the authorization server issues a signed token during the OAuth flow, then steps aside. MCP traffic goes straight from client to MCP server, which validates the token locally against the cached JWKS — no per-request hop through the authorization server.* **The honest trade-off** is revocation timing. Because validation is local and offline, a revoked token is not rejected instantly everywhere. It stays valid until it expires or until the next check against revocation state. That is exactly why token lifetime matters in this pattern: short-lived tokens keep the window small. Naming this trade openly is the difference between an accurate description and a sales pitch. ## So which one do you actually need? The honest answer is that they are usually not substitutes, and many production systems want both. A gateway does traffic policy. An authorization server does identity and consent. They sit at different layers and solve different problems. The failure mode to avoid is running a gateway with nothing behind it. A gateway can enforce that a request carries a token. It cannot, on its own, decide who should have gotten that token, what scopes it should carry, or which user delegated the authority. Without an authorization server making those decisions, the gateway is enforcing a policy that was never actually defined. If you only stand up one of the two, an authorization server is the one that answers the questions auth is actually for. ## Where AuthPlane sits AuthPlane is an authorization server, not a gateway. It runs alongside your MCP server rather than in front of it. It issues and signs tokens, your server validates them locally against the JWKS, and your MCP traffic never passes through us. If you also want edge traffic policy, put a gateway in front and let it do that job while AuthPlane handles identity, consent, and token issuance behind it. ## The bottom line If you take one thing from this: "MCP auth" is two jobs, not one. Decide whether you need traffic enforcement, identity and consent, or both, and pick the component that matches each. You do not need a gateway to have real MCP auth, and you should not treat a gateway as a substitute for an authorization server. See how the alongside-not-in-front model works in practice: [github.com/AuthPlane](https://github.com/AuthPlane). ## Sources 1. MCP Authorization specification, 2025-11-25. 2. RFC 9728, OAuth 2.0 Protected Resource Metadata (discovery and validation model). --- # MCP 2026-07-28: what changes for authorization - Published: 2026-07-24 - Tag: SPEC - URL: https://authplane.ai/blog/mcp-2026-07-28-authorization/ - Excerpt: What the MCP 2026-07-28 specification changes for authorization: the stateless core, OAuth-aligned SEPs, the deprecation policy, and what to check before the July 28 final. > **Update, September 15, 2026.** The 2026-07-28 specification shipped on schedule and is now the current version on modelcontextprotocol.io. AuthPlane v0.2.0 implements its authorization surface end to end, and was verified by hand with Claude Desktop, Claude Code and MCP Inspector — see the [client compatibility matrix](https://github.com/AuthPlane/authserver/blob/main/docs/reference/mcp-client-compatibility.md). The piece below is as written the week before release; "until the 28th" has passed. *The next MCP specification finalizes on July 28. Here is what moves on the authorization side, and what to check before it lands.* ## TL;DR - The 2026-07-28 specification is the largest MCP revision since launch. The release candidate locked on May 21, 2026, and the final publishes on July 28, 2026. - The headline change is a stateless protocol core. On the authorization side, a set of SEPs aligns MCP more closely with how OAuth 2.0 and OpenID Connect are actually deployed. - A formal deprecation policy guarantees a minimum twelve-month window, so nothing breaks on July 29. - The current finalized version is still 2025-11-25. If you cite a version anywhere, that is the one to cite until the 28th. *(Since September 2026: cite 2026-07-28.)* If you run an MCP server, the practical question about the 2026-07-28 spec is short: do you have to do anything before it lands? For most teams the honest answer is "not urgently," and this piece explains why. It also covers what is actually changing on the authorization side, since that is the part that tends to get lost under the louder headline about the stateless core. ## What is shipping, and when Per the [Model Context Protocol release-candidate announcement](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/), the release candidate locked on May 21, 2026, and the final specification publishes on July 28, 2026. The roughly ten-week gap is a validation window for SDK maintainers and client implementers to test against real workloads before the final. One detail trips up a lot of the coverage, so it is worth getting right. MCP versions are date-stamped to mark the last date backwards-incompatible changes were made. "2026-07-28" is a version label, not the day a blog post went up, and not a deadline you personally have to hit. Until the 28th, the current finalized version remains 2025-11-25, which is the version to reference in your own docs and compliance statements in the meantime. ## What changes on the authorization side The release candidate groups the authorization work into six Specification Enhancement Proposals (SEPs). The through-line is consolidation toward how OAuth 2.0 and OpenID Connect are already deployed: fewer MCP-specific quirks, more of the patterns a security team already recognizes from standard OAuth. Notably, most of the six place their requirements on the client or the MCP server rather than the authorization server. {% table %} - SEP - What it changes - Primarily affects --- - SEP-2468 - The authorization server should include an issuer (`iss`) parameter in its authorization responses, including errors, per RFC 9207, and advertise support in its metadata. - Authorization server --- - SEP-837 - Clients declare `application_type` (native or web) during Dynamic Client Registration, so an authorization server does not wrongly reject a CLI's localhost redirect. - Client and AS behavior --- - SEP-2352 - Clients key their stored credentials by issuer and re-register if the authorization server changes. - Client --- - SEP-2207 - Clients may request `offline_access` for refresh tokens, while the authorization server keeps full discretion over whether to issue them. - Client --- - SEP-2350 - Scope accumulation across step-up authorization is a client responsibility, and MCP servers should challenge with the specific scopes an operation needs rather than the union of all scopes. - Client and MCP server --- - SEP-2351 - Confirms MCP uses the standard `oauth-authorization-server` discovery suffix (RFC 8414) and defines no MCP-specific one. - AS discovery {% /table %} The pattern is worth stating plainly, because it is the reassuring part: only one of the six, SEP-2468, adds a new requirement on the authorization server itself, and it is a SHOULD, with the spec signaling a future revision will raise it to a MUST. The rest are client-side, MCP-server-side, or confirmations of behavior that a standards-based authorization server already follows. ## What this means if you have a server in production The headline change, the stateless core, is the one with practical consequences. If your server quietly relies on session state held between calls, that dependency is now the thing to find and remove before you adopt the new transport behavior. This is worth doing regardless of the authorization changes. On timing, the panic framing that some of the coverage is selling is not warranted. The new lifecycle policy guarantees a minimum twelve-month window between a feature being deprecated and removed. Nothing that works on July 28 stops working on July 29. You have a real transition period, and the calm reading of this release is the accurate one. ## Where AuthPlane stands We build directly against the MCP authorization spec, so here is our honest status against the six proposals, written before the final ships. Five of the six place their requirements on the client or the MCP server, or confirm behavior AuthPlane already implements, including the discovery suffix (SEP-2351) and refresh-token issuance (SEP-2207). The one net-new requirement that lands on the authorization server itself is SEP-2468, issuer identification in authorization responses. It is currently a SHOULD, and the spec signals a future revision will make it a MUST. We are implementing it ahead of that change. It is a small, well-scoped addition rather than a structural one. We are not claiming day-one conformance to a spec that has not finalized, and we would rather name the one open item than imply there are none. *This page has been updated since the final published — see the dated note at the top. A dated page that visibly maintains itself is more useful, and more trustworthy, than one that quietly goes stale.* ## The bottom line The 2026-07-28 spec is a big release, but for authorization it is a consolidation toward standard OAuth rather than a rewrite of what you know. Find any hidden session state now, note the twelve-month deprecation window, and keep citing 2025-11-25 until the 28th. If you want an authorization server that tracks these revisions so you do not have to, that is what we are building: [github.com/AuthPlane](https://github.com/AuthPlane). ## Sources - Model Context Protocol, The 2026-07-28 Specification Release Candidate. - MCP Authorization specification, 2025-11-25 (finalized version at time of writing). - MCP Authorization specification, 2026-07-28 (current). - Akamai, The New MCP Specification: What Security Teams Must Prepare For. --- # Open source MCP auth: what your options actually are - Published: 2026-07-24 - Tag: COMPARISON - URL: https://authplane.ai/blog/open-source-mcp-auth/ - Excerpt: The four real ways to put OAuth 2.1 in front of an MCP server, what each covers, and where each falls short. Keycloak, a cloud IdP, rolling your own, or a server built for MCP. *Four ways to put OAuth 2.1 in front of an MCP server, and the point where each one runs out of road.* ## TL;DR - Four real options: Keycloak, a cloud identity provider, build it yourself, or a server built for MCP. They all work. - Keycloak covers the OAuth core but does not read the `resource` parameter, so you bind token audiences by hand, one mapper per server. - Two questions usually settle it: can your tokens leave your network, and do your agents act on each other's behalf? You built an MCP server. It runs. Now you want agents other than your own to reach it, and the auth you put off is the thing between you and production. Once the server is remote, the MCP spec expects OAuth 2.1, so that static key in your `.env` is not a long-term answer. If it is any comfort, you are in a crowd. Astrix Security analyzed more than 5,200 open-source MCP servers for its [State of MCP Server Security 2025](https://astrix.security/learn/blog/state-of-mcp-server-security-2025/) report, published that October. 88% require some credential, 53% run on a long-lived static key or personal access token, and 8.5% use OAuth. The study read repository READMEs rather than code, so treat the split as directional. The direction is unambiguous, and nothing since suggests it has reversed. There are four realistic ways to get a spec-compliant OAuth 2.1 layer in front of your server. Here is each one, and where it falls short. ## What the MCP spec requires of an authorization server "Does it do OAuth" is not a useful question. The spec is specific about which requirements land on the authorization server, which land on the client, and which land on your MCP server. Getting those confused is where most of the confusion starts. These levels are from the [authorization section of the spec](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization). {% table %} - Requirement - Who / level - What it does --- - OAuth 2.1 - AS: MUST - Authorization code flow with mandatory PKCE for public clients. --- - A discovery mechanism - AS: MUST provide one - Either RFC 8414 metadata or OpenID Connect Discovery, so clients can find its endpoints. --- - Client ID Metadata Documents (CIMD) - AS and client: SHOULD - A newer registration approach used by clients like VS Code and Claude Code. --- - Dynamic Client Registration (RFC 7591) - AS and client: MAY - Registration with no prior relationship. Now deprecated in favor of CIMD (see below). --- - Resource Indicators (RFC 8707) - Client MUST send; server MUST validate - Binds a token to one MCP server. The client sends `resource`; your server rejects tokens not issued for it. --- - Issuer identification (RFC 9207) - AS: SHOULD send; client MUST validate - The AS returns `iss` in the authorization response; the client checks it before redeeming the code. Closes the authorization-server mix-up attack. New in 2026-07-28, and the spec signals it will become a MUST for the AS. {% /table %} **Three things to pull out of that.** The spec does not require the authorization server to support RFC 8707. It requires the client to send the `resource` parameter and your MCP server to validate the audience, so an authorization server that ignores `resource` is still usable, you just have to arrange the binding another way. Protected Resource Metadata (RFC 9728) is a MUST, but it belongs to your MCP server, not the authorization server. And RFC 9207 is the newest arrival: no authorization server in this comparison has published a compliance position on it yet, which makes it the thing to ask any vendor about. One update: the current spec is 2026-07-28, and it deprecates Dynamic Client Registration (DCR) in favor of Client ID Metadata Documents (CIMD). DCR still works for now. Most authorization servers, Keycloak included, have not fully caught up to that revision yet, which is worth keeping in mind as you read the rest. We go through the revision in detail in [MCP 2026-07-28: what changes for authorization](/blog/mcp-2026-07-28-authorization). ## Option 1: Keycloak for MCP auth Keycloak is the first name most people reach for, and that is a fair instinct. It is a CNCF project, it has been in production for a decade, and if you already run it for employee SSO, adding a realm for MCP is a Tuesday. The OAuth core is solid. Per [Keycloak's own MCP guide](https://www.keycloak.org/securing-apps/mcp-authz-server), it supports OAuth 2.1, RFC 8414 metadata, and Dynamic Client Registration, and it can do Client ID Metadata Documents behind an experimental flag (`kc.sh start --features=cimd`). The snag is Resource Indicators. Keycloak's compliance table lists RFC 8707 as "Not supported," and the guide puts it bluntly: Keycloak cannot recognize the `resource` parameter. Keycloak is hard on itself about this, grading its own MCP conformance "Partially Supported without Resource Indicators." Read strictly, the spec is more forgiving: it puts the resource-parameter MUSTs on the client and on your MCP server, and tells clients to send the parameter "regardless of whether authorization servers support it." Either way the practical consequence is the same. Your MCP server still has to reject tokens that were not minted for it, and reading `resource` is the clean way an authorization server sets that audience. Without it, you set the audience yourself. Here is what "yourself" looks like, straight from Keycloak's instructions. Say your server is `https://example.com/mcp` with three scopes. You create a client scope for each one, then add an Audience mapper to each with the server URL typed into the Included Custom Audience field. Three scopes, three mappers, one server. The result is a token with the right `aud`: ```json { "aud": "https://example.com/mcp", "scope": "mcp:tools mcp:prompts mcp:resources" } ``` It works, and the docs walk you through every click. It is also configuration you own and repeat for every server you protect, and native `resource` support is on the Keycloak community's roadmap rather than in a release. If you already live in Keycloak and do not mind the mapping, this is a real path. If you are standing auth up for agents specifically, that per-server step is the thing to weigh. ## Option 2: a cloud identity provider (Auth0, WorkOS, Descope) Auth0, WorkOS, Descope, Stytch, Scalekit. Managed OAuth you point at, where someone else absorbs the spec churn every time MCP revises. WorkOS pitches exactly that: paste a URL, skip the authorization-server plumbing. The catch is location. Your tokens, and the identity behind them, pass through a third party. Plenty of teams are fine with that. Some vendors offer dedicated or private-cloud deployments that answer a geographic residency requirement, though the service is still operated by the vendor on their schedule. If your constraint is an on-prem mandate, or a rule that identity data cannot leave your perimeter at all, no managed option clears it, and this branch closes before the feature comparison starts. ## Option 3: build your own MCP authorization server The spec is public and for one server it looks like a weekend. The first version usually is. Nobody quotes you for the maintenance. A real authorization server means a dozen or more OAuth RFCs, plus key rotation, JWKS, refresh rotation with replay detection, and an audit trail you can hand to a reviewer. Then the spec moves. It has revised four times since launching in November 2024, 2025-03-26, 2025-06-18, 2025-11-25, and now 2026-07-28, and the latest revision deprecates DCR for CIMD. Building it yourself means signing up to chase that indefinitely. Most teams did not set out to run an identity team. ## Option 4: a purpose-built MCP authorization server This is where AuthPlane sits, so read it as one of the four rather than a sales turn. It is an open-source OAuth 2.1 authorization server for MCP. The server is AGPL-3.0, the SDKs are Apache-2.0. That licensing line tends to be the first thing an engineering manager forwards to legal, so it is worth saying up front. It is a single Go binary with an admin UI built in, and it runs next to your MCP server instead of in front of it. Your server validates tokens locally against the JWKS, so only the OAuth flows touch AuthPlane and nothing sits in your request path. That distinction is the subject of its own piece, [authorization server or gateway](/blog/mcp-auth-without-gateway), if the difference is not obvious. Tokens are short-lived and audience-bound, and scopes go down to the tool level. When the calling client is registered as an agent, the token also carries its identity and the delegation chain: a record of which agent made the call and on whose behalf. Non-agent traffic, like service-to-service calls and admin operations, is issued without those claims, so your MCP server can tell agent-mediated requests from the rest. Chains nest up to five hops by default, and the flattened chain claim holds eight entries. On agent identity across the field: Keycloak has no native concept of it. Among the cloud providers it varies. Auth0 shipped Agents as Principal, currently in Early Access, which gives an agent its own stable identifier and audit trail. The rest treat an agent as just another OAuth client. On the audience question that trips up Keycloak: AuthPlane reads the `resource` parameter and stamps the audience into the token automatically, on every grant. You register a server once, and there is no per-server mapper to maintain. Matching is exact: the resource identifier has to match what you registered, with no prefix or wildcard matching. ## Open source MCP auth options compared Rows are the requirements from the top. Every cell about a third party is sourced. {% table %} - Capability - Keycloak - Cloud IdP - Build your own - AuthPlane --- - OAuth 2.1 + PKCE - Yes - Yes - You build it - Yes --- - Discovery (8414 / OIDC) - Yes - Yes - You build it - Yes --- - Audience binding (`resource`) - Manual, per server - Varies by vendor - You build it - Yes, automatic --- - Agent identity + delegation - No native concept - Varies: Auth0 ships Agents as Principal (EA); others none - You build it - Native --- - Self-hosted - Yes - No - Yes - Yes --- - Data-residency options - Yes - Dedicated / private cloud from some vendors - Yes - Yes --- - Who tracks spec revisions - Community-paced - Vendor - You - Maintainers, shipped as releases {% /table %} *One note on that last row. As of publication, no authorization server in this table had published a 2026-07-28 compliance statement, AuthPlane included. Update, September 2026: AuthPlane v0.2.0 implements 2026-07-28 end to end and publishes its [compliance statement](https://github.com/AuthPlane/authserver/blob/main/docs/reference/compliance.md) and a [client compatibility matrix](https://github.com/AuthPlane/authserver/blob/main/docs/reference/mcp-client-compatibility.md). The row describes who owns the upgrade work, not who has finished it.* ## When Keycloak (or no authorization server) is the right call A comparison that only points one direction is not worth your time, so here is where AuthPlane is not the answer. If you already run Keycloak for human SSO, have no residency constraint, and your agents do not delegate to each other, extending what you already operate beats adding a component. And if you are one person running a single local server with no delegation and nothing regulated, you may not need an authorization server at all. A static key on localhost is fine. ## Which MCP auth option should you pick? The destination is not in question. The spec already picked it: OAuth 2.1, audience-bound tokens, real scopes, a discovery endpoint. You are choosing the road. Keycloak if you already run it and can live with the manual mapping. A cloud IdP if your tokens are allowed to leave. Roll your own if you want to own the treadmill. And if you would rather have the agent-specific pieces handled and keep your infrastructure yours, that is the fourth option. AuthPlane is open source and self-hosted. Point it at your own server and see where it holds up: [github.com/AuthPlane](https://github.com/AuthPlane). ## Sources 1. MCP Authorization specification, 2026-07-28 (current). 2. Keycloak, Integrating with Model Context Protocol (MCP). 3. Astrix Security, State of MCP Server Security 2025. 4. Auth0 Docs, Agents as Principal. 5. RFC 8414, OAuth 2.0 Authorization Server Metadata. 6. RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol. 7. RFC 8707, Resource Indicators for OAuth 2.0. 8. RFC 9207, OAuth 2.0 Authorization Server Issuer Identification. 9. RFC 9728, OAuth 2.0 Protected Resource Metadata. --- # The Upside and Downside of MCPs: A Practical 2026 Guide - Published: 2026-06-25 - Tag: EDUCATION - URL: https://authplane.ai/blog/upside-and-downside-of-mcps/ - Excerpt: In 2026, the hardest part of shipping an AI agent isn't the model, it's the plumbing. MCP was designed to fix the integration tangle, and two years in it largely has, but production teams have discovered real trade-offs along the way. In 2026, the hardest part of shipping an AI agent isn't the model, it's the plumbing. Every enterprise AI project hits the same wall: the model is capable, but connecting it to internal tools, data, and services means maintaining a tangle of custom connectors. Each new AI vendor adds another integration. Each new tool adds another adapter. Before long, the integration layer is the project. Model Context Protocol (MCP) was designed to fix that. Two years in, it largely has but production teams have discovered real trade offs along the way. Here's what works, what doesn't, and how to ship MCP without getting burned. **TL;DR:** Model Context Protocol (MCP) is an open standard that gives AI agents a uniform way to discover and use external tools, data, and services. Its primary upside is collapsing the integration matrix from N×M custom connectors to N+M reusable pieces. Its primary downsides cluster around authentication, governance, stateful session scaling, and context management. Most production teams find the standardization win outweighs the friction, provided MCP is paired with proper auth (such as OAuth 2.1) and good audit tooling. ## What Is MCP? Model Context Protocol (MCP) is an open standard introduced by Anthropic in November 2024. It defines how AI applications such as Claude, ChatGPT, and other LLM-based agents connect to external tools, data sources, and services using JSON-RPC 2.0. Think of MCP as a universal port for AI, similar in concept to USB-C for hardware. An AI agent that speaks MCP can plug into any MCP server, regardless of what that server connects to behind the scenes. The protocol is now governed by the Agentic AI Foundation under the Linux Foundation, with founding sponsorship from Anthropic, Block, and OpenAI, and broader support from Google, Microsoft, AWS, and Cloudflare. By mid-2026, the ecosystem includes over 3,000 published MCP servers, with directories like Smithery cataloging 7,000+ and mcp.so listing 19,700+. Every major IDE has shipped MCP support. ## The Upside of MCPs ### 1. Standardization Solves the N×M Integration Problem Before MCP, every new AI model that wanted to talk to a tool needed a custom connector. With four models and five tools, that meant maintaining twenty separate integrations. MCP collapses that to N+M: each client implements the protocol once, each server implements it once, and they all interoperate. For enterprises with dozens of internal systems, this is the difference between a manageable integration layer and an unsustainable one. Forrester predicts roughly 30% of enterprise app vendors will launch their own MCP servers in 2026, and industry projections suggest 75% of API gateway vendors and 50% of iPaaS vendors will support MCP features by year-end. ### 2. Dynamic Tool Discovery Traditional APIs require the calling code to be pre-programmed with knowledge of what each endpoint does. MCP supports runtime capability discovery: an agent can query an MCP server and learn what tools are available, what arguments they accept, and what they return, without anyone modifying the agent. That changes the economics of adding new tools. A team can ship a new MCP server and have every compatible client see it on the next session, without coordinating a release with the AI vendor. ### 3. A Real Ecosystem Already Exists The network effect is genuine. Most common tools your agent might need already have a working MCP server, often more than one. That means new builders can focus on what is novel about their product, rather than rebuilding integrations from scratch. Anthropic, OpenAI, Google, Microsoft, AWS, and Cloudflare all participate in the spec process, which keeps the protocol moving forward without locking adopters into a single vendor. ### 4. Future-Proofing Your APIs If you wrap your existing API behind an MCP server, you do not need to predict which AI vendor wins the agent race. Any MCP-compatible client (Claude Desktop, Cursor, VS Code, MCP Inspector, ChatGPT, custom orchestrators) can use your tool through the same interface. You ship one server; the ecosystem brings the clients. That kind of leverage is rare in software. ### 5. Faster Development Cycles for Builders An MCP server that works in a demo can be ready in a weekend. Official SDKs exist for Go, TypeScript, Python, C#, Java, and Rust, which means teams can use languages they already know. The hard parts of integration (message format, error handling, capability negotiation) are handled by the protocol itself. For internal tools or proof-of-concept work, this lowers the activation energy. ### 6. Modular, Replaceable Architecture Each MCP server is independently deployable. You can swap one out, version it, scale it, or replace its underlying implementation without touching the agent or other servers. The separation of concerns mirrors microservice patterns and ages well as your stack grows. ## The Downside of MCPs The same standardization that makes MCP attractive also exposes assumptions that older API patterns never had to handle. Most of the well-known downsides are real but tractable. Here are the ones that matter most in 2026. ### 1. Authentication Is the hard part Building an MCP server is a one-afternoon job. Securing it is not. Consider Alice, a data analyst at a regional healthcare network. She asks Claude to pull last quarter's patient cohort data so she can prep for a board meeting. Claude makes the MCP call using Alice's OAuth token, a token scoped to read every dataset she has access to. The audit log records "Alice" as the caller. Claude actually made the call. Now imagine Alice had earlier asked Claude to summarize a third-party report containing a prompt-injection payload. That payload could silently redirect the cohort query to exfiltrate patient records to an external endpoint and the audit log would still say Alice. This is not a theoretical edge case. It is the default behavior of any MCP deployment running on long-lived, broadly scoped credentials. API keys were designed for a world where the entity calling your API is the same entity that owns the key. In MCP, that is no longer true. When Alice opens Claude and asks it to "check my GitHub PRs," Claude calls your MCP server using credentials from Alice's context. The audit log says Alice called your endpoint. Claude actually did. You cannot tell the difference. Four assumptions break under the agent model: 1. **The caller is not the key owner.** Identity resolution becomes ambiguous. 1. **The scope was set at key creation, not at the moment of action.** There is no contextual consent. 1. **Every MCP tool now needs to validate keys against a central service.** That introduces a bottleneck and a single point of failure. 1. **MCP clients expect to discover auth endpoints via standard metadata.** API keys do not provide this. This is why OAuth 2.1 has become the recommended pattern for MCP authorization, formalized in the MCP Authorization Spec (2025-11). Self-hosted solutions like AuthPlane exist specifically to handle this layer, so teams can add OAuth 2.1 to an MCP server in roughly ten minutes without rolling their own crypto or coordinating a dozen RFCs by hand. ### 2. Context Bloat and Memory Management As context accumulates across an agent session, MCP implementations can suffer from context bloat. Stored or referenced information becomes excessive, slowing down processing and injecting irrelevant data into the model's reasoning. Many current implementations lack built-in TTLs, summaries, or compression strategies. That leaves teams to build context management themselves, often after the fact when latency starts to climb. ### 3. Limited Cross-Session Generalization MCP preserves context within a defined boundary, like a chat thread or an agent task. It does not learn broader user preferences across sessions or applications. For products that rely on long-term user modeling, MCP is a single layer, not the full solution. ### 4. Stateful Sessions Conflict With Load Balancers Production deployments have exposed gaps in how MCP handles state. Stateful sessions can clash with horizontal scaling: if the same client connects to a different server instance, session state can be lost. This is one of the four priorities on the official MCP 2026 roadmap. Until the relevant Spec Enhancement Proposals (SEPs) land, teams need to plan their own session affinity or session store strategy. ### 5. Governance and Audit Trails Were an Early Gap Compliance teams asking "who authorized this MCP action?" often find the answer harder than it looks. In an API key model, your logs show that Alice's key was used. It does not show that Alice's AI agent used it, but rather that Alice did. There is no consent record for that specific action. Mature deployments need: - Mandatory logging fields: timestamp, session, tool name, parameters, result summary, and auth context - Automatic PII flagging on tool calls that access or return personal data - Full delegation chain traces from user to orchestrator to sub-agent The 2026 MCP roadmap addresses governance directly, with active SEPs for DPoP (SEP-1932) and Workload Identity Federation (SEP-1933). ### 6. Multi-Agent Pipelines Are Hard to Trace When an orchestrator calls a sub-agent that calls your MCP tool, all three hops can appear in your audit log as a single user, without delegation-aware tokens, such as those built on RFC 8693 Token Exchange with act. Sub claims that you cannot see who built the pipeline or whether the user authorized every step. For regulated industries (financial services, healthcare, defense), this is a meaningful audit gap. ### 7. The Enterprise Surface Is Still Maturing MCP is moving from developer tooling toward enterprise infrastructure. Enterprise-readiness work, including SSO integration, gateway behavior, and configuration portability, is the least defined of the four 2026 roadmap priorities. Adopters today should plan for spec updates and treat the 2025-11 Authorization Spec as a baseline, not a ceiling. ## How to Mitigate the Downsides Most of the issues above have known mitigations. Here is the practical playbook: {% table %} - Challenge - Mitigation --- - Authentication - Use OAuth 2.1 with the MCP Authorization Spec; consider a dedicated MCP auth server --- - Context bloat - Implement TTLs, summarization, and compression in your agent layer --- - Stateful sessions - Use sticky sessions or externalize state into Redis or Postgres --- - Audit gaps - Capture consent events at token issuance, not just at request time --- - Delegation tracing - Use Token Exchange (RFC 8693) to carry the delegation chain --- - Cross-session memory - Layer a memory system above MCP, not inside it --- - Client discovery - Serve /.well-known/oauth-authorization-server and RFC 9728 Protected Resource Metadata. {% /table %} ## Should You Adopt MCP? MCP is worth adopting when: - AI agents will use your product from multiple vendors - You want a single integration surface instead of one per LLM provider - You expect the agent ecosystem to keep growing, which it is You should plan carefully when: - You operate in a regulated industry where audit and identity requirements are strict - Your existing API uses static keys that AI clients cannot easily discover - You need an on-premises deployment for compliance reasons For most teams shipping AI products in 2026, the question is no longer whether to adopt MCP, but how to layer the right auth, audit, and memory patterns on top of it. ## Ready to Secure Your MCP Deployment? Try AuthPlane If this post has made one thing clear, it's that auth isn't an afterthought in MCP; it's the difference between a demo and a production system you can trust. **AuthPlane** is an open source MCP authorization server that adds OAuth 2.1 to your MCP stack in about 10 minutes. No crypto wrangling, no RFC spelunking. Just plug it in, configure your scopes, and get a proper delegation chain with audit trails that actually show who (and what) made each call. **What you get out of the box:** - OAuth 2.1 with PKCE — the pattern the MCP Authorization Spec recommends - Per-session, per-tool scope enforcement (so Alice's token can't do more than Alice intended) - Delegation tracing so your audit log shows the agent, not just the user - A /.well-known/oauth-authorization-server endpoint for compliant client discovery **Get started:** → [Star AuthPlane on GitHub](https://github.com/authplane/authserver) and follow the quickstart → Drop into the community to ask questions or contribute The authentication gap in MCP is real — but it's also solved. You don't have to ship with long-lived API keys and hope nothing goes wrong. ## Frequently Asked Questions ### What Does MCP Stand For? MCP stands for Model Context Protocol. It is an open standard for connecting AI models to external tools and data sources, introduced by Anthropic in November 2024. ### Is MCP a Replacement for APIs? No. MCP sits on top of APIs. It standardizes how AI agents discover and call tools, while the underlying API still handles the actual data operations. ### Who Governs MCP? MCP is governed by the Agentic AI Foundation under the Linux Foundation, with founding sponsorship from Anthropic, Block, and OpenAI, and broader ecosystem support from Google, Microsoft, AWS, and Cloudflare. The project maintainers retain full technical autonomy. ### What Are the Biggest MCP Security Risks? The largest risks come from unauthenticated tool exposure, prompt injection, missing identity context for agents acting on a user's behalf, and weak audit trails. OAuth 2.1, DPoP (RFC 9449), and Token Exchange (RFC 8693) address the most serious gaps. ### How Long Does It Take to Build an MCP Server? A demo-quality MCP server can be built in a weekend using the official SDKs. A production-quality MCP server with authentication, auditing, scope enforcement, and multi-tenant support is a longer project, typically taking weeks. ### Will MCP and A2A (Agent-to-Agent) Compete? They serve different layers. MCP is agent-to-tool. A2A is agent-to-agent. Most enterprise deployments in 2026 use both MCP for tool access and A2A for cross-vendor agent coordination. ### Is MCP Production-Ready in 2026? Yes, with the caveat that enterprise-grade auth, audit, and scaling patterns need to be added on top of the base protocol. The 2026 roadmap explicitly targets these gaps, and tooling around the protocol continues to mature. ### What Languages Have MCP SDKs? Official MCP SDKs exist for Go, TypeScript, Python, C#, Java, and Rust, covering most enterprise stacks. ## Sources - Anthropic, "MCP Authorization Specification" (2025-11) - Model Context Protocol Blog, "The 2026 MCP Roadmap" (March 2026) - CallSphere Blog, "MCP 2026 Roadmap: Scalability, Enterprise Auth, and Governance" - Truto, "What Is MCP (Model Context Protocol)? The 2026 Guide - Databricks, "What Is the Model Context Protocol (MCP)?" - Google Cloud, "What Is Model Context Protocol (MCP)? A Guide" - Veran/AuthPlane technical documentation on MCP authentication --- # Cross-App Access: Why Enterprise MCP Needs IdP-Mediated Authorization - Published: 2026-03-21 - Tag: SPEC - URL: https://authplane.ai/blog/cross-app-access-enterprise-mcp-authorization/ - Excerpt: XAA (Cross-App Access) puts the enterprise IdP in the loop for every agent-to-tool connection. Here's how ID-JAG works, why it matters, and how AuthPlane implements it. ## The Shadow IT Problem in Agent Authorization When an MCP client connects to an MCP server today, it establishes a direct OAuth connection. The agent asks the user for consent, the user approves, and a token is issued. This works — but enterprise IT has zero visibility into what just happened. Every agent-to-tool connection is a bilateral trust relationship between the MCP client and the MCP server. InfoSec can't see it, can't audit it, and can't revoke it from a central place. Each connection is effectively shadow IT. In a world where a single developer might have dozens of agents connecting to dozens of tools, this creates a sprawling web of ungoverned access that no compliance framework can accept. ## What is Cross-App Access? Cross-App Access (XAA) — the market name coined by Okta for the **Identity Assertion JWT Authorization Grant (ID-JAG)** — is an OAuth 2.0 extension being standardized through the IETF OAuth Working Group. It inserts the enterprise Identity Provider into the authorization flow as the central policy decision-maker. Instead of apps establishing bilateral trust with each other, every agent-to-tool connection goes through the enterprise IdP. The IdP decides whether the connection is allowed, what scopes are granted, and logs the decision. The user never sees a consent screen — the enterprise policy replaces it. The MCP specification formalized this as **SEP-990: Enterprise-Managed Authorization** in the November 2025 update, making it a first-class extension of the MCP auth model. ## The Three-Party Token Exchange XAA involves three parties: the **MCP Client** (requesting app), the **Enterprise IdP** (policy authority), and the **MCP Server** (resource app via AuthPlane). 1. **User authenticates via SSO.** The user logs into the MCP client through their corporate identity provider — standard OIDC. They get an ID token. 2. **MCP client requests an ID-JAG.** The client sends a Token Exchange request (RFC 8693) to the IdP's token endpoint. It asks for an assertion JWT targeted at the specific MCP server it wants to access. 3. **IdP evaluates policy.** The IdP checks enterprise policy: Is this app-to-app connection allowed? What scopes? Does the user's group membership qualify? Is step-up auth required? 4. **IdP issues the ID-JAG.** If policy passes, the IdP returns a signed JWT — the ID-JAG assertion. It's audience-bound to the downstream MCP server, contains the approved scopes, and is short-lived — AuthPlane rejects any ID-JAG older than 5 minutes by default. 5. **MCP client presents ID-JAG to AuthPlane.** Using the JWT Bearer grant type (`grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer`), the client presents the assertion to AuthPlane. 6. **AuthPlane validates and issues an access token.** AuthPlane verifies the JWT signature against the IdP's JWKS endpoint, checks audience binding, validates the JTI for single-use, evaluates its own policy engine, and issues a short-lived access token. The entire exchange happens without user interaction after the initial SSO login. No consent screen. No redirect. No popup. ## Why Not Standard OAuth? Standard OAuth creates direct trust between client and server. The user authorizes the connection, and the client gets a token. This is fine for consumer apps where the user is the authority. But in enterprise, the organization is the authority — not the individual user. With XAA, IT/InfoSec can: - **Pre-approve or deny connections** — before any user can authorize them - **Enforce scope restrictions** — the IdP decides what scopes are allowed, not the user - **Require step-up auth** — high-privilege connections can demand MFA - **Revoke access instantly** — from a single point, for all users, for a specific app pair - **Audit everything** — every connection decision is logged at the IdP ## Security Invariants AuthPlane enforces strict security invariants on every ID-JAG assertion it processes: - **Algorithm restrictions:** `alg:none` and all HMAC algorithms (`HS256`, `HS384`, `HS512`) are rejected. Only asymmetric algorithms (ES256, RS256) are accepted. - **Single-use assertions:** Every JTI is consumed atomically. Replay is impossible. - **Short-lived:** Maximum assertion lifetime of 5 minutes (configurable down, never up). - **Audience binding:** The assertion's `aud` claim MUST match AuthPlane's issuer URL. - **Client binding:** The `client_id` in the assertion MUST match the authenticated client. - **No refresh tokens:** JWT Bearer grants never produce refresh tokens. Every access token requires a fresh assertion from the IdP. - **SSRF protections:** JWKS fetch URLs are validated against an allowlist. No internal network access. - **Policy evaluation:** Every assertion passes through the policy engine before token issuance. ## How AuthPlane Implements XAA AuthPlane's XAA implementation is built on four components: ### Trusted IdP Registry Administrators register enterprise IdPs with their issuer URL and JWKS endpoint. AuthPlane discovers and caches the IdP's signing keys with automatic rotation. Only registered IdPs can issue assertions that AuthPlane will accept. ### JWT Bearer Grant Type (RFC 7523) AuthPlane's token endpoint accepts `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer`. It validates the assertion signature, checks all security invariants, and maps the assertion claims to an access token. ### Policy Engine Before issuing a token, AuthPlane evaluates configurable policy rules: subject mapping (how IdP users map to AuthPlane principals), scope restrictions (what scopes are allowed for this IdP/client pair), and group-based access control. ### Audit Trail Every assertion validation — successful or rejected — is logged with the full context: IdP issuer, subject, client, requested scopes, policy decision, and resulting token (if issued). This gives compliance teams a complete audit trail of every enterprise-mediated agent connection. ## What This Means for Regulated Industries SOC 2, HIPAA, and FedRAMP all require centralized access governance. XAA transforms agent authorization from an ungovernable sprawl of bilateral OAuth connections into a centrally managed, auditable, and revocable system. The enterprise IdP — the same system that already governs employee access to every other application — now governs agent access too. For compliance teams, this means: - Every agent-to-tool connection is visible in the IdP's access log - Access reviews cover agent connections alongside human access - Offboarding a user or decommissioning an agent revokes all their connections from one place - Scope restrictions are enforced by policy, not by trusting individual users to grant appropriate permissions XAA is available now in AuthPlane. See the [quickstart guide](https://docs.authplane.ai/quickstart/) to deploy, or check the [source on GitHub](https://github.com/authplane/authserver). --- # OAuth 2.1 + PKCE Is the Only Right Way to Secure MCP - Published: 2026-03-04 - Tag: SPEC - URL: https://authplane.ai/blog/why-mcp-needs-oauth-21-pkce/ - Excerpt: The MCP authorization spec mandates OAuth 2.1 with mandatory PKCE for a reason. Here's exactly why every alternative falls apart. ## Why MCP Needs OAuth 2.1 When Anthropic published the MCP authorization specification, they made a clear choice: OAuth 2.1 with mandatory PKCE, not a simpler token scheme. This wasn't arbitrary. MCP servers are HTTP services that expose tools to AI agents. HTTP already has a mature, widely-adopted authorization framework. The question was never *whether* to use OAuth — it was *which version*, and with *what constraints*. ## The Problem with Older OAuth Flows OAuth 2.0 (RFC 6749) was published in 2012. In the years since, a number of its flows have been deprecated because they create real security vulnerabilities: - **Implicit grant**: Access tokens returned directly in the redirect URI fragment. Tokens end up in browser history, server logs, and HTTP referrer headers. Omitted from OAuth 2.1 (and deprecated earlier by the OAuth 2.0 Security BCP, RFC 9700). - **Resource Owner Password Credentials**: User passes credentials directly to the client. Omitted from OAuth 2.1 (RFC 9700 deprecated it). - **Authorization code without PKCE**: Vulnerable to authorization code interception attacks — an attacker who intercepts the code can exchange it for a token. ## PKCE: Why S256 Only PKCE (RFC 7636) adds a cryptographic binding between the authorization request and the token exchange. The client generates a random `code_verifier`, computes `code_challenge = BASE64URL(SHA256(code_verifier))`, and sends the challenge upfront. When exchanging the code, the server verifies `SHA256(verifier) == stored_challenge`. The critical detail is **S256 only**. The RFC also defines a `plain` method where the verifier *is* the challenge — no hashing. `plain` still stops an attacker who only intercepts the authorization code, but it collapses the moment the attacker can also see the authorization request, where the verifier travels in the clear (RFC 7636 §7.2). S256 closes that gap, so AuthPlane rejects `plain` at the protocol level. Every authorization request without `code_challenge_method=S256` is rejected immediately. ## Single-Use Authorization Codes Authorization codes are single-use and expire in 10 minutes. Consumption is atomic in the database — using `UPDATE ... WHERE consumed_at IS NULL RETURNING *`. If the row is already consumed, no rows are returned and the exchange fails. An attacker who intercepts a code after the legitimate client already exchanged it gets nothing. ## Refresh Token Rotation and Theft Detection Access tokens expire in 15 minutes. Refresh tokens rotate on every use and belong to a *family*. If a consumed token is ever presented again, the entire family is revoked immediately. If an attacker steals a refresh token, the next legitimate refresh by the real client reveals the theft and terminates all sessions in the family. ## Summary OAuth 2.1 with mandatory S256 PKCE provides what MCP agents need: protection against code interception, cryptographic binding between the authorization and exchange steps, and removal of deprecated flows. AuthPlane implements all of this from the RFC, not a library — no hidden defaults to hit. --- # What We Saw When Teams Shipped MCP Without Auth - Published: 2026-03-01 - Tag: SECURITY - URL: https://authplane.ai/blog/what-happens-without-mcp-auth/ - Excerpt: Four real attack patterns observed in unprotected MCP deployments: token replay, log scraping, scope escalation, and zero audit trail. ## The Problem with "We'll Add Auth Later" MCP servers are built by developers who know their tools work. They test locally, everything connects, the agent makes tool calls, it's great. Auth is the last thing anyone wants to think about. And then they ship it. Here's what we've observed in unprotected deployments. Not theoretical — observed. ## Attack Pattern 1: Token Replay Without auth, MCP tool calls often carry whatever credential the agent was given at startup — an API key, a service account token, sometimes a personal access token. These tokens are passed in HTTP headers. MCP servers that log request headers (which many do for debugging) now have those tokens in log files. Log files that get rotated to S3. S3 buckets with misconfigured access policies. Anyone who can read the logs gets a working token with no expiry and no audit trail of what they did with it. With AuthPlane MCP Auth: access tokens are JWTs that expire in 15 minutes. They're bound to specific MCP servers via the `aud` claim, set from the RFC 8707 `resource` parameter. Even if someone extracts a token from a log, it's expired and scoped to a single server. ## Attack Pattern 2: No Scope Enforcement Many MCP servers expose tools like `execute_query`, `write_file`, `send_email`. Without auth, every agent that connects gets access to every tool. There's no way to give one agent read-only access and another write access. There's no way to restrict a debugging agent from sending emails. AuthPlane MCP Auth implements tool-level scopes. A token for `tools/read_db` cannot call `tools/write_db`. The consent screen shows users exactly which tools an agent is requesting. Requests for unscoped tools return `403 insufficient_scope`. ## Attack Pattern 3: No User Identity in Tool Calls When an agent calls a tool, the MCP server often doesn't know *which user* triggered it. This matters for multi-tenant systems. Without identity in the request, there's no way to enforce row-level security, rate limits per user, or audit which user's agent made a sensitive call. With AuthPlane JWTs, every tool call carries `sub` (user ID), `agent_id` (which agent), and `agent_chain` (delegation path). MCP servers can enforce per-user and per-agent policies on every request. ## Attack Pattern 4: Zero Audit Trail When something goes wrong — an agent deletes data it shouldn't have, sends an email it wasn't supposed to, makes an API call that burns through rate limits — there's no way to reconstruct what happened without auth. No record of which agent made the call, on behalf of which user, at what time, with what inputs. AuthPlane's audit log captures every token issuance, every revocation, every consent decision, every refresh. Stored with `trace_id` and `span_id` for correlation with request traces. ## The Fix The fix is straightforward: deploy AuthPlane MCP Auth alongside your MCP server. It handles the full OAuth 2.1 flow and takes under 5 minutes to deploy. Your MCP server gets a JWKS endpoint to verify tokens against, and every tool call arrives with a verified JWT that tells you exactly who the agent is, which user authorized it, and what tools it's allowed to call. --- # Reading RFC 9728 - Published: 2026-02-26 - Tag: SPEC - URL: https://authplane.ai/blog/reading-rfc-9728-protected-resource-metadata/ - Excerpt: Protected Resource Metadata is how MCP agents discover authorization servers. Here is the full walkthrough of the spec and how AuthPlane implements it. ## What RFC 9728 Is RFC 9728 (Protected Resource Metadata) defines how an OAuth-protected resource server advertises its authorization server(s) to clients. For MCP, this is the discovery mechanism that allows agents to find the right authorization server without any configuration. Before RFC 9728, a client needed to know out-of-band which authorization server to use. With RFC 9728, the MCP server tells the client where to go. The client can walk into any MCP server it has not seen before and know exactly how to authenticate. ## The Well-Known URL RFC 9728 defines a standard discovery URL path: `/.well-known/oauth-protected-resource`. An MCP server that implements the spec exposes a metadata document at this URL. No authentication required to fetch it — it is a public advertisement. ``` GET /.well-known/oauth-protected-resource HTTP/1.1 Host: api.yourmcpserver.example.com ``` The response is a JSON document: ```json { "resource": "https://api.yourmcpserver.example.com", "authorization_servers": [ "https://auth.yourdomain.example.com" ], "scopes_supported": [ "tools/read_db", "tools/write_db" ], "bearer_methods_supported": ["header"] } ``` ## The Key Fields **`resource`**: The canonical identifier for the protected resource. This becomes the `aud` (audience) claim in access tokens. When a token is issued, the authorization server sets `aud` to this value. The MCP server verifies that the token audience matches its identifier. This prevents token substitution attacks — a token issued for one MCP server cannot be used at another. **`authorization_servers`**: The list of OAuth 2.1 authorization servers that can issue tokens for this resource. The client picks one and initiates the OAuth flow. AuthPlane MCP Auth is the authorization server you would list here. **`scopes_supported`**: The scopes available on this resource. By AuthPlane convention, scopes are named `tools/tool_name` (the MCP spec leaves scope naming to the resource server). This is what appears in the user consent screen when an agent requests access. ## How AuthPlane Implements RFC 9728 AuthPlane handles both sides. For the authorization server side, AuthPlane exposes its own metadata document at `/.well-known/oauth-authorization-server` (RFC 8414). Clients that reach AuthPlane can discover all its capabilities: supported grant types, token endpoint, JWKS URI, and more. For the resource side, your MCP server needs to expose `/.well-known/oauth-protected-resource`. The MCP SDKs handle this automatically when you configure the resource identifier and authorization server URL. ## Why This Matters for Agents Agents built on Claude Code, Claude Desktop, or custom orchestration frameworks can use RFC 9728 to connect to MCP servers they have never seen before. The agent fetches the discovery document, finds the authorization server URL, initiates OAuth 2.1, and gets a token scoped to exactly the tools it requested. No configuration files. No hardcoded endpoints. RFC 9728 is the first step in that fully automatic flow.