Do AI Agents Need SPIFFE or OAuth?

SPIFFE proves which agent process is calling; OAuth scopes what it may do and for whom. When each is enough, and when production agents need both.

They answer different questions. SPIFFE proves which process is calling, without a provisioned secret. OAuth scopes what it may do and, when a human is in the loop, for whom. Most production agent platforms need both, joined by assertion or token exchange. Neither is a winner.

Disclosure: I work at Solo.io, which created agentgateway and sells Solo Enterprise for agentgateway. The demos I cite are public repositories.

This page is the when-each. The how-to is SPIFFE identity for AI agents , where I ran agentgateway + SPIRE until agent-alpha got HTTP 200 and agent-beta got HTTP 403. I am not rewriting that demo. Architecture context is what an agentic mesh is . Identity as an evaluate row is how to choose an AI agent gateway .

The short answer

SPIFFE/SPIRE gives an agent an attested, short-lived workload identity (an SVID) so the platform can prove which process is calling without a long-lived secret at rest. OAuth gives a scoped, audience-restricted access token, and a delegation story (on-behalf-of) when a user is in the loop. OAuth alone does not attest the runtime. SPIFFE alone does not carry permissions or a user.

Enough alone only in the narrow cases in the table below. Production platforms usually run both.

Lin Sun’s CNCF post Agent Auth: a lawyer’s day in court is the metaphor I would paste into the ADR: the lawyer is not the client. The agent is not the user. You need agent identity, principal identity, and a delegation artifact, then policy on top.

Two different questions

Stop treating them as rivals. I already wrote the sentence on the demo page: identity is not authorization. A verified name is not a permission.

What a SPIFFE ID gives you (and what it refuses to give)

SPIRE attests the calling process (in my demo, a docker label; on Kubernetes, namespace and service account) and issues a short-lived X.509 or JWT SVID from the Workload API. There is no key file to mount. The certificate lives minutes and rotates in place.

What you get: a verified name (spiffe://example.org/ns/demo/sa/agent-alpha), mTLS or a JWT-SVID, and a bootstrap that does not start with a provisioned secret.

What you do not get: a permission model, scopes, audiences for third-party APIs, or a human sub. The demo’s agent-beta holds a perfectly valid SVID and still gets 403, because CEL allows only agent-alpha. That is the point.

What an OAuth token gives you (and what it refuses to give)

An access token is a permission envelope: scopes, audience, expiry, and (with OBO) a user. A resource can decide what this caller may do, and for whom.

What you do not get: platform attestation that this process is the agent. A client secret or a private key the agent holds is possession of a credential, not workload identity. A fleet that shares one client_id audits a credential, not a workload. Stolen bearer tokens are ambient authority until they expire.

MCP’s shipped enterprise auth authenticates the employee through an IdP, not the unattended agent. I walked that in MCP agent identity .

When each is enough

SituationReach forBecause
In-cluster agent → gateway → model, one trust domain, no human OBOSPIFFE (or mesh equivalent)Policy can be an ACL on source.spiffeId. I ran this.
Agent acting for a logged-in humanBothYou need the agent principal and an OBO / subject token.
Third-party SaaS APIs that only speak OAuth client authOAuth, plus SPIFFE in front if you can attest the callerThe SaaS will not verify your SVID. The gateway still should.
CI, laptop, or serverless with no SPIREOAuth or platform OIDCYou cannot attest the workload the SPIFFE way yet. Say so.
Multi-hop agent → agentBoth, joined by exchangeEach hop needs a new audience. Do not forward the same bearer.
MCP tools with different risk profilesBothA SPIFFE name is not a tool allowlist; a user token is not a workload.

SPIFFE-only (honest scope)

Same trust domain you control end to end. Policy is an ACL on the SPIFFE ID at the gateway. No human OBO required.

That is the SPIFFE demo . verify.sh asserts the claims rather than narrating them:

verifying...
  ok    no certificate or key files in the repo
  ok    gateway config contains no cert or key path
  ok    agent-alpha gets HTTP 200
  ok    agent-alpha holds no provider credential
  ok    upstream authenticated the gateway's SVID
  ok    agent-beta gets HTTP 403
  ok    gateway echoes the verified SPIFFE ID

7 passed, 0 failed

The agent reports provider credentials I hold: {'env': 'none', 'key_files': 'none'} and still gets a 200, because the gateway attached the upstream key. The upstream saw sa/agentgateway, not sa/agent-alpha. Identity terminated at the hop. That is SPIFFE-only plus secretless injection, which is still not a permission envelope for a third-party API.

OAuth-only (honest scope)

No platform attestation available (developer laptop, customer-managed runtime), or you only call APIs that only accept OAuth client authentication. agentgateway’s MCP auth (OAuth per the MCP auth spec) is a fine starting point. Disclose the limits: shared secrets, fleet-wide client_id, stolen bearer, audit that names a credential not a workload.

Do not pretend a virtual key the agent holds is SPIFFE.

Both (the usual production answer)

SVID (or platform OIDC) authenticates the agent. An OAuth access token carries scopes, audience, and (when needed) the user. They join in two documented ways:

  1. SVID as client credential. draft-ietf-oauth-spiffe-client-auth-02 , an OAuth working-group Internet-Draft (not yet an RFC), profiles RFC 7521 / RFC 7523 so a workload presents a JWT-SVID, WIT-SVID, or X.509-SVID as the client assertion. No static client secret.
  2. SVID as actor token. Ping’s token exchange + workload identity pattern uses RFC 8693: subject_token is the user, actor_token is the JWT-SVID, result is an audience-restricted access token for the next hop.

agentgateway can perform RFC 8693 token exchange on the outbound path: incoming token becomes subject_token, the exchanged token is what the backend sees. That token-exchange page is Kubernetes docs. The SPIFFE and secretless demos ran on OSS v1.5.0 standalone. Pair inbound SPIFFE from the demo with outbound exchange when you are on the Kubernetes path.

Audience restriction is the OAuth-shaped control that sits next to workload identity. kagent v0.10 can send an RFC 8707 resource indicator on the exchange; both env vars default to empty (audience-bound agent tokens ).

How they join on an agent path

One hop list. No new repo.

  1. The agent fetches an SVID from the Workload API (no cert file).
  2. It presents that SVID as a client assertion, or the gateway/STS takes it as actor_token.
  3. The authorization server mints an access token for one audience, with the scopes that hop needs.
  4. The gateway verifies SPIFFE on the wire, authorizes the tool or model, and (if the backend wants OAuth) forwards the exchanged token.
  5. Provider keys stay at the gateway (secretless ). MCP tool allowlists stay at the gateway (federation , run on Solo Enterprise for agentgateway).

Do not pass bearer JWT-SVIDs down an agent chain. A JWT-SVID copied to agent B is onwards impersonation, not proof-of-possession. Mint a new, audience-restricted token per hop.

Gateway as the enforcement hop

This is the agentic mesh picture in one sentence: verify SPIFFE on the wire, inject secretless provider creds, authorize tools. The gateway is where “both” becomes a path instead of an IdP slide. Score that path with the evaluate-gateway identity row. I run it on agentgateway, standalone or on Kubernetes.

Identity on the intended path is not enough if agents CONNECT elsewhere. That failure is egress bypasses .

Failure modes if you pick only one

OAuth-only. Shared client secrets, one client_id for the fleet, stolen bearer, audit without a workload name. A prompt file does not fix it (AGENTS.md is not a security control ).

SPIFFE-only. A name mistaken for permission (the demo’s 403 is there so you do not do this). No human attribution when the agent acts for a user. Third-party APIs still want OAuth. Multi-tenant tool entitlements still need something that is not only source.spiffeId.

Is SPIFFE overkill for a small team?

Often, yes, as step one.

Start with platform OIDC or standalone agentgateway and hard scopes. Add SPIRE when you have multi-team agents, a shared MCP plane, or a compliance need for attested workload identity. That is the same fork as the evaluate-gateway identity criterion. You do not owe anyone a SPIRE DaemonSet on week one of a single-provider prototype.

Where to go next on webofmike

External primaries:

The OSS project is agentgateway/agentgateway . This page is a when-each, not a claim that SPIFFE replaces OAuth.

Frequently asked questions

Do AI agents need SPIFFE, or is OAuth enough?

They answer different questions. SPIFFE/SPIRE gives an agent an attested, short-lived workload identity (an SVID) so the platform can prove which process is calling without provisioning a long-lived secret. OAuth gives a scoped, audience-restricted access token, and when a human is in the loop, a delegation story (on-behalf-of), so a resource can decide what that caller may do. OAuth alone does not attest the runtime; SPIFFE alone does not carry permissions or a user. For most production agent platforms the honest answer is both, joined by federation or token exchange, not a single winner.

When is SPIFFE enough, and when is OAuth enough?

SPIFFE alone can be enough when every callee sits in a trust domain you operate end to end and policy can be an ACL on the SPIFFE ID at the gateway (agent to gateway to model, no human OBO). OAuth alone can be enough when you cannot attest the workload (laptop, customer-managed runtime) or you only call third-party APIs that only accept OAuth client authentication, accepting secret or key lifecycle and weaker what-process-is-this guarantees. Neither is enough by itself when agents act for users across tools with different risk profiles: you need attested agent identity and a permission or delegation envelope.

When do AI agents need both SPIFFE and OAuth?

When the agent must prove it is a specific attested workload and present a scoped token for a resource or a user delegation, typical for multi-team agents, MCP tool planes, and multi-hop agent chains. Practically: fetch an SVID from the Workload API, present it as a client assertion (or as the RFC 8693 actor_token), receive an audience-restricted access token, and enforce at the gateway. Do not treat a verified SPIFFE ID as implicit authorization, and do not pass bearer JWT-SVIDs down a delegation chain as if they were proof-of-possession.