DEV Community

Yolanda Robla Mota
Yolanda Robla Mota

Posted on

Beyond API Keys: Token Exchange, Identity Federation & MCP Servers

Modern backend systems—especially in the era of AI agents, MCP servers, and multi-cloud architectures—are evolving far beyond static credentials and monolithic identity models. In this post we explore the architecture of token exchange, identity federation, and how a system like ToolHive enables secure deployment of MCP servers in this world.

The legacy problem: static credentials

The MCP authorization specification focuses on how to authorize access to the MCP server itself. It doesn't specify how an MCP server should authenticate with the server it's connecting to. This leaves MCP server creators without clear guidance.

In many deployments of MCP (Model Context Protocol) servers and tooling services today, developers still default to patterns like:

  • A service-account JSON key or a long-lived API key embedded in configuration.
  • All calls executed under a single “shared identity” with elevated permissions.
  • If the key is compromised, the impact spans many users or tenants; rotating or tracking the key is operationally heavy.
  • Least-privilege is often compromised because the shared identity needs broad access to avoid blocking tool invocation.

This approach doesn’t align with how modern identity systems, federated services and cloud tools are designed. It’s less secure, harder to govern, and doesn’t scale across users or multi‐tenant environments.

Step up: Short-lived tokens via an IdP

A much better pattern emerges when you shift to short-lived tokens:

  • A user (or service) authenticates via an Identity Provider (IdP) — for example, Okta or Azure AD.
  • They receive a short-lived token (OIDC ID token or OAuth access token) that's scoped to their identity and minimal permissions.
  • This token is used to authenticate to the MCP server (with the help of ToolHive), which validates it and establishes the user's identity.
  • Toolhive then acquires a separate token for the downstream backend API—either through token exchange (if using the same IdP) or federation (if crossing identity domains).
  • Your MCP server receives this backend-scoped token and uses it when calling downstream services or tools.

Because tokens are scoped, time-limited, and mapped to a specific user context, you get better auditability, enforce least-privilege, and eliminate static credentials. Next, we’ll show you how to ensure that your MCP server always has the right credentials for its backend API without embedding secrets or handling complex auth flows.

Token Exchange & Federation: crossing trust-boundaries

Token exchange refers to the process where one security token (issued by one identity domain) is presented to a “Security Token Service” (STS) or similar endpoint, and in return you receive a new token valid for another domain, audience, or scope.
The standard for this is RFC 8693 (OAuth 2.0 Token Exchange) which lets you request a new token via a grant like urn:ietf:params:oauth:grant-type:token-exchange

Use-cases for token exchange include:

  • A token issued by your internal IdP being exchanged for a token valid for a cloud provider’s API.
  • A token from one IdP being reused to obtain tokens in another trust domain without forcing the user to log in again.
  • A service acting on behalf of a user, exchanging its own token for one with narrower scopes or different audiences.

Two common scenarios

A) The downstream service uses the same IdP as the MCP server

In this case your identity provider (IdP) issues tokens for both the MCP server and the downstream resources. No cross-domain trust is needed.

  • User authenticates via IdP → obtains a token for the MCP server.
  • ToolHive validates the token and performs access control checks.
  • ToolHive exchanges that token with the same IdP for a new token with the downstream service's audience and scopes.
  • MCP server receives this exchanged token and uses it to call the downstream service. ​​- Simpler, fewer moving parts, since the exchange happens within the same IdP ecosystem.

Token exchange diagram

The token issued to the client might look like this (simplified):

{
   "iss": https://idp.example.com/oauth2/default",
   "aud": "**mcp-server**",
   "scp": [
     "**backend-mcp:tools:call**",
     "**backend-mcp:tools:list**",
   ],
   "sub": "user@example.com",
}
Enter fullscreen mode Exit fullscreen mode

While the exchanged token would have different scopes and a different audience, allowing the MCP server to authenticate to the back end service:

{
    "iss": https://idp.example.com/oauth2/default",
    "aud": "**backend-server**",
    "scp": [
        "**backend-api:read**",
    ],
    "sub": "user@example.com",
}
Enter fullscreen mode Exit fullscreen mode

B) The downstream service uses a different IdP and you rely on federation

Here you have two distinct identity/trust domains: one used by the MCP server (or its IdP) and another used by the back end resource. Instead of issuing separate credentials or having users login twice, you rely on federation and token exchange.

  • User authenticates via IdP A → receives a token for domain A that is presented to ToolHive
  • ToolHive validates the token and performs access control checks.
  • ToolHive presents the token to an STS or federation service (e.g., Google Cloud STS) → obtains a federated token valid for domain B (cloud provider).
  • Downstream service validates the token from domain B and executes requests under that identity.

This approach enables your system to be IdP-agnostic and cloud-agnostic: authenticate with any IdP, then federate into any trust-configured domain.

Flow diagram about federation

The token issued to the client might look like this (simplified):

{
  "iss": "**https://idp.example.com/oauth2/default**",
  "aud": "**mcp-server**",
  "sub": "user@example.com",
  "email": "user@example.com",
  "scp": [
    "**mcp:tools:call**",
    "**mcp:tools:list**"
  ],
  "exp": 1729641600,
  "iat": 1729638000
}
Enter fullscreen mode Exit fullscreen mode

The exchanged federated access token would have a different issuer, audience, and scopes, allowing the MCP server to authenticate to the upstream service as the federated user identity:

{
  "iss": "**https://sts.googleapis.com**",
  "aud": "**https://bigquery.googleapis.com/**",
  "sub": "**principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/user@example.com**",
  "email": "user@example.com",
  "scp": [
    "**https://www.googleapis.com/auth/bigquery**",
  ],
  "exp": 1729641600,
  "iat": 1729638000
}
Enter fullscreen mode Exit fullscreen mode

Why this matters for MCP servers

  • MCP servers are often deployed to call different services on behalf of users. If they rely on static credentials or simplistic “shared identity” models, you lose user-level attribution, least-privilege control, and auditability.
  • By using token exchange + federation, you allow your MCP server to operate under the right identity context, even when the target service sits in a different trust domain.
  • It also lets you design your architecture so the authentication piece (login, token issuance) is decoupled from the MCP server logic — the server can remain auth-agnostic and medium-agnostic.

Where ToolHive fits

ToolHive simplifies deployment of MCP servers by handling the operational and security heavy-lifting.

  • You run your MCP servers in containers with minimal permissions and network access — ToolHive manages that.
  • ToolHive acts as a gateway: it verifies the user's token (via your IdP), enforces access policies, then acquires the appropriate backend token—either through exchange or federation—before passing that to your MCP server.
  • This separation means your MCP server remains auth-agnostic — ToolHive handles authN/authZ and you plug in any IdP or downstream STS.

This blog post is the first in a series. Over the coming posts we’ll dive into a set of practical examples using ToolHive — showing how to wire up different IdPs, federate into different clouds, run MCP servers securely, and deal with real-world edge cases.

Note: ToolHive is an open source project, and we encourage you to download it (from toolhive.dev) and start using it. We value your feedback and would love to engage with you via our GitHub repo and/or Discord channel.

Top comments (0)