Skip to main content

OAuth Server and Token Exchange

Defakto gives every workload in a trust domain a SPIFFE identity, which workloads use to prove who they are to each other. Some calls need something more than, or different from, a workload's SPIFFE Verifiable Identity Document (SVID). Common examples include:

  • The service expects OAuth. MCP servers, and many APIs, accept only OAuth access tokens.
  • A person needs access, not only a workload. People reach your services through applications such as Claude, a web app, or a command-line tool, and sign in with your company's identity provider.
  • A downstream service needs to know who the user is. When a workload acts for a person, the services it calls often need to see that person as well as the calling workload.
  • The service is outside your trust domain. A third-party service accepts only its own credentials, such as a long-lived client secret, rather than SPIFFE identities. You don't want to give every workload that secret.

For cases like these, each trust domain has an OAuth authorization server. The OAuth server runs in the same Trust Domain Servers that already issue your SVIDs, at the address you already expose through your load balancer, so it needs no additional deployments or infrastructure. A caller presents a credential it already has, such as its SVID, a person's sign-in, or a token from your identity provider, and receives the token it needs next. Every request is checked against a token policy that you control.

What you can do​

These are some of the most common uses of the OAuth server.

Use caseGuide
Protect your MCP server so that workloads and people can call itHost an MCP server
Let your workloads call MCP servers and other OAuth-protected services with their SPIFFE identitiesCall an MCP server from a workload
Act on behalf of a user: pass the end user's identity and context to downstream services, optionally through multiple hopsPropagate a user's identity
Give workloads short-lived tokens for third-party services without distributing those services' static secretsGet tokens for external services

Built on OAuth standards​

Every flow is based on open standards, so existing OAuth clients and libraries work with it. These are some of the standards involved:

StandardWhat Defakto uses it for
OAuth 2.0 authorization code grantPeople sign in through an application, such as an MCP client, and the application receives an access token for them.
JWT bearer grant (RFC 7523)A workload presents its JWT-SVID and receives an access token. Many providers call this pattern workload identity federation.
Token exchange (RFC 8693)A workload presents a token it already holds, such as a user's token, and receives a different one, such as an OBO token.
Transaction Tokens (IETF draft)A short-lived token that records who started a transaction and travels with it.

One policy for every flow​

Every request, whatever the flow, goes through the same token policy. The token policy decides whether to issue a token and what the token contains. Its rules match requests by four properties: the caller, the user the caller acts for (if any), the type of token requested, and the service the token is for.

  • Deny rules block matching requests.
  • Allow rules permit matching requests, and can narrow the token they produce, such as limiting its scopes or setting its lifetime.
  • External authorizer rules send matching requests to a webhook you run, such as your own policy engine, for the final decision.
  • A default decides requests that no rule matches.
  • A kill switch refuses every request immediately.

Every decision is recorded on an audit event.

For example, this token policy lets agent workloads get access tokens for the helpdesk MCP server with read-only scope:

policy:
authorization:
unmatched: deny
allow:
- name: agents-read-tickets
match:
caller:
spiffeID: spiffe://example.com/ns/agents/**
requestedTokenType: urn:ietf:params:oauth:token-type:access_token
audience: https://helpdesk.example.com/mcp
token:
allowedScopes: [tickets.read]

See the token policy reference for every rule field.

How you configure it​

The OAuth server is configured with one OAuthServer Managed Configuration section per trust domain:

OAuthServer
├── endpoints Where browsers and applications reach the OAuth server
├── identityProviders[] Who vouches for people: your identity providers
├── oauthClients[] OAuth clients you trust, by their client ID URLs
├── externalResources[] Third-party APIs that Defakto gets tokens for
├── authorizers[] Your own decision webhook, if you use one
└── policy The token policy: access decisions, scopes, lifetimes, and claims

You can apply Managed Configuration through the Defakto API, Terraform, or the Defakto CLI. See applying configuration. For example, with the CLI:

defakto config set trust-domain --id <trust-domain-id> oauth-server.yaml

Next steps​

  • To set up a specific use case, choose a scenario.
  • To look up a configuration field, token claim, or error, see the reference.