Backend authentication
This document explains how ToolHive helps MCP servers authenticate to third-party APIs and backend services exposed through the MCP servers. You'll learn about the backend authentication patterns ToolHive supports, why they improve security and multi-tenancy, and how they simplify MCP server development.
This documentation covers MCP-server-to-backend authentication—how MCP servers authenticate to external services or APIs they call (for example, a GitHub MCP server authenticating to the GitHub API).
This is different from client-to-MCP-server authentication, which involves how clients authenticate to the MCP server itself. That topic is covered in Authentication and authorization.
The challenge of backend authentication
The MCP specification focuses on authorization to the MCP server but doesn't specify how an MCP server should authenticate to the services it exposes. This is intentionally left to implementers, which makes sense from a specification perspective but leaves MCP server developers without clear guidance.
Many MCP servers today either embed static API keys or require custom authentication code. This creates several problems:
- Security risks: Long-lived credentials stored in configuration files or environment variables can be compromised
- Audit challenges: When multiple users share a service account, you can't trace individual actions
- Multi-tenancy complexity: Supporting multiple tenants with isolated credentials requires significant custom code
ToolHive addresses these challenges with three backend authentication patterns: static credentials for services that don't support OAuth, token exchange for services in the same or federated trust domain, and the embedded authorization server for OAuth-based external APIs where no federation exists.
How ToolHive handles backend authentication
ToolHive sits between clients and MCP servers, and can acquire backend
credentials on behalf of the MCP server. Depending on the pattern, it might
exchange the client's token, run an OAuth flow against an external provider, or
inject static credentials. In each case, the MCP server receives ready-to-use
credentials—via an Authorization: Bearer header, another header, or
environment variables, depending on the pattern—without needing to implement
custom authentication logic or manage secrets directly.
Backend authentication patterns
ToolHive supports three patterns for backend authentication. Which one you use depends on the relationship between your identity provider (IdP) and the backend service.
Static credentials and API keys
When a backend service requires API keys, database passwords, or other static credentials, you can configure them directly in ToolHive as environment variables, secret files, or injected headers.
This is the simplest pattern, but it provides the least security and auditability. Static credentials are long-lived and shared across all users, so there is no per-user attribution in audit logs.
When using static credentials, consider integrating with a secret management system like HashiCorp Vault for secure storage and rotation.
Token exchange
When the backend service trusts the same IdP as your MCP clients—or federation is configured between the two IdPs—ToolHive can exchange the client's token for one scoped to the backend service using RFC 8693 token exchange. This preserves the user's identity across services and provides short-lived, narrowly scoped tokens. Because the trust relationship between services is pre-configured at the IdP, no consent screen or user interaction is required—the exchange is transparent to the end user.
Same IdP with token exchange
When both the MCP server and the backend service trust the same IdP, and that IdP supports RFC 8693 token exchange, ToolHive can exchange the internal token for an external one.
How it works:
- The user authenticates to the MCP client and receives an access token from the IdP
- ToolHive's token exchange middleware contacts the IdP, presenting the user's access token
- The IdP issues a new access token with different audience and scopes
- ToolHive passes this access token to the MCP server
- The MCP server uses the access token to call the upstream service
Federated IdPs with identity mapping
When the backend service trusts a different IdP, but federation is configured between the two IdPs, ToolHive can use the federated identity service to issue short-lived tokens. An example is Google's Security Token Service (STS), which can issue tokens for Google Cloud services based on your corporate identity.
How it works:
- The user authenticates to their MCP client with a corporate IdP and receives token_A
- ToolHive submits token_A to the federated identity service
- The federated service maps the identity and issues token_B
- ToolHive passes token_B to the MCP server
- The MCP server uses token_B to call the upstream service
Embedded authorization server
When the MCP server needs to call an external API where no federation relationship exists—such as GitHub, Google Workspace, or Atlassian APIs—the embedded authorization server handles the full OAuth web flow against the external provider. The proxy redirects the user to authenticate directly with the external service, obtains tokens on behalf of the user, and passes the upstream token to the MCP server.
How it works:
- The client connects to ToolHive
- ToolHive redirects the user to the external provider (for example, GitHub) for authentication
- The user authenticates with the external provider
- ToolHive receives an authorization code and exchanges it for upstream tokens
- ToolHive stores the upstream tokens and issues its own JWT to the client
On subsequent MCP requests, ToolHive uses the JWT to retrieve the stored upstream tokens and forward them to the MCP server. For details on this mechanism, see Token storage and forwarding.
The embedded authorization server runs in-process within the ToolHive proxy—no separate infrastructure is needed. It supports Dynamic Client Registration (DCR), so MCP clients can register automatically with ToolHive—no manual client configuration in ToolHive is required.
The embedded authorization server is currently available only for Kubernetes deployments using the ToolHive Operator.
Key characteristics
- In-process execution: The authorization server runs within the ToolHive proxy—no separate infrastructure or sidecar containers needed.
- Configurable signing keys: JWTs are signed with keys you provide, supporting key rotation for zero-downtime updates.
- Flexible upstream providers: Supports both OIDC providers (with automatic endpoint discovery) and OAuth 2.0 providers (with explicit endpoint configuration).
- Configurable token lifespans: Access tokens, refresh tokens, and authorization codes have configurable durations with sensible defaults.
- Dynamic Client Registration (DCR): Supports OAuth 2.0 Dynamic Client Registration (RFC 7591), allowing MCP clients to register automatically with ToolHive's authorization server—no manual client registration in ToolHive is required.
- Direct upstream redirect: The embedded authorization server redirects clients directly to the upstream provider for authentication (for example, GitHub or Atlassian).
- Single upstream provider: Currently supports one upstream identity provider per configuration.
The embedded authorization server redirects clients directly to the upstream provider. This means the upstream provider must be the service whose API the MCP server calls. Chained authentication—where a client authenticates with a corporate IdP like Okta, which then federates to an external provider like GitHub—is not yet supported. If your deployment requires this pattern, consider using token exchange with a federated identity provider instead.
Token storage and forwarding
The embedded authorization server stores upstream tokens (access tokens, refresh
tokens, and ID tokens from external providers) in session storage. When the
OAuth flow completes, the server generates a unique session ID and stores the
upstream tokens keyed by this ID. The JWT issued to the client contains a tsid
(Token Session ID) claim that references this session.
When a client makes an MCP request with this JWT:
- The ToolHive proxy validates the JWT signature and extracts the
tsidclaim - It retrieves the upstream tokens from session storage using the
tsid - The proxy replaces the
Authorizationheader with the upstream access token - The request is forwarded to the MCP server with the external provider's token
This mechanism allows MCP servers to call external APIs with the user's actual credentials from the upstream provider, while the client only needs to manage a single ToolHive-issued JWT.
In Kubernetes deployments, session storage is currently in-memory only. Upstream tokens are lost when pods restart, requiring users to re-authenticate.
For the client-facing OAuth flow, see Embedded authorization server. For Kubernetes setup instructions, see Set up embedded authorization server authentication.
Token exchange in depth
This section provides implementation details for the token exchange patterns described above. For setup instructions, see Configure token exchange (CLI) or Configure token exchange in Kubernetes.
Token exchange implementation
The token exchange flow demonstrates how ToolHive transforms user identity tokens into properly scoped service tokens.
Token transformation
When a client authenticates to ToolHive, it receives a token scoped for the MCP server:
{
"iss": "https://idp.example.com/oauth2/default",
"aud": "mcp-server",
"scp": ["backend-mcp:tools:call", "backend-mcp:tools:list"],
"sub": "user@example.com"
}
ToolHive's token exchange middleware contacts the IdP and exchanges this token for one scoped to the backend service:
{
"iss": "https://idp.example.com/oauth2/default",
"aud": "backend-server",
"scp": ["backend-api:read"],
"sub": "user@example.com"
}
Notice how the audience (aud) and scopes (scp) change while preserving the
user's identity (sub). This exchanged token is then injected into the
Authorization: Bearer HTTP header and passed to the MCP server.
Federation flow
When using federated identity providers, ToolHive can map your corporate identity to an external service identity. This is particularly useful for accessing cloud services like Google Cloud Platform.
The client authenticates with your corporate IdP and receives a token:
{
"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
}
ToolHive's token exchange middleware calls the external Security Token Service (STS) endpoint. For Google Cloud, this looks like:
POST https://sts.googleapis.com/v1/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&audience=//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
&scope=https://www.googleapis.com/auth/bigquery
&requested_token_type=urn:ietf:params:oauth:token-type:access_token
&subject_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
&subject_token_type=urn:ietf:params:oauth:token-type:jwt
The federated service returns a token that maps your corporate identity to a federated principal:
{
"iss": "https://sts.googleapis.com",
"sub": "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/user@example.com",
"aud": "https://bigquery.googleapis.com/",
"email": "user@example.com",
"scope": "https://www.googleapis.com/auth/bigquery",
"exp": 1729641600,
"iat": 1729638000
}
This exchanged token is injected into the Authorization: Bearer HTTP header
and passed to the MCP server. The MCP server uses this token to make upstream
API calls, with each request attributed to the individual user's federated
identity rather than a shared service account.
Key differences from standard token exchange
Federation-based token exchange has several important characteristics:
- No client authentication required: The external STS endpoint doesn't
require
client_idorclient_secret. The OAuth JWT itself serves as proof of identity. - Identity federation pool as intermediary: The
audienceparameter points to a federation pool configuration, not directly to the target service. - Principal mapping: User attributes (email, sub) from the OAuth token are mapped to federated principals for access control.
- Individual audit trail: Upstream service audit logs show the individual user identity, not a service account.
Security and operational benefits
ToolHive's backend authentication patterns provide several key advantages:
- Secure: MCP servers receive short-lived, properly scoped access tokens instead of embedding long-lived secrets
- Auditable: Each API call is attributed to the individual user identity, making audit trails clear and meaningful
- Multi-tenant friendly: Token scoping naturally supports tenant isolation and separation of duties
- Developer friendly: MCP servers don't need custom authentication logic—they just use the provided token
- Least privilege: Tokens are narrowly scoped to specific audiences and permissions, reducing the blast radius if compromised
- Consistent: The same pattern works across different backend services and identity providers
Choosing the right backend authentication model
| Scenario | Pattern | Why |
|---|---|---|
| Backend only accepts API keys or static credentials | Static credentials | No OAuth support; configure credentials directly in ToolHive |
| Backend trusts the same IdP as your clients | Token exchange (same IdP) | Exchange the client token for a backend-scoped token via RFC 8693 |
| Backend trusts a federated IdP (for example, Google Cloud) | Token exchange (federation) | Map your corporate identity to the federated service |
| Backend is an external API with no federation (for example, GitHub) | Embedded authorization server | Run the full OAuth flow against the external provider |
Related information
- For client authentication concepts, see Authentication and authorization
- For the embedded authorization server, see Embedded authorization server
- For configuring the embedded authorization server in Kubernetes, see Set up embedded authorization server authentication
- For configuring token exchange, see Configure token exchange (CLI) or Configure token exchange in Kubernetes
- For policy configuration, see Cedar policies