Skip to content
agentgateway has joined the Agentic AI FoundationLearn more

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Backend authentication

Page as Markdown

Attach the gateway’s own credential to requests that it forwards to a backend.

Backend authentication is how the gateway proves its own identity to an upstream service. Client authentication is the opposite direction: how a client proves its identity to the gateway. The two are separate settings, and most routes need both.

A request therefore carries up to two credentials at different points in its life. The client sends one to the gateway, and the gateway sends a different one to the backend. What connects them is that the client credential is often what the gateway uses to get the backend credential.

Choose a method

Start from what the upstream expects, not from what the client sends.

The upstream expectsUseWhere the credential comes from
A fixed API key or tokenStatic keyA value that you configure, or a Secret or file that you control
The credential that the client already sentPassthroughThe incoming request
A token issued by AWS, Azure, or Google CloudCloud provider credentialsThe cloud provider, in exchange for the gateway’s own identity
A GitHub Copilot tokenCloud provider credentialsThe environment of the gateway process
A JWT signed by your private key, fresh on every requestSigned JWTThe gateway signs one per request from a key that you supply
A narrower token, derived from the client’s credential at one authorization serverOAuth token exchangeAn authorization server, in exchange for the client credential
A token from an authorization server that did not authenticate the userCross App AccessTwo authorization servers, across a trust boundary

The families in more detail:

  • Static key. The simplest case, and the right one whenever the backend issues you a long-lived credential. Prefer a Secret or a file over an inline value, so that the credential is not stored in the configuration.
  • Passthrough. Sends the client credential on to the backend unchanged. Use it when the backend validates the same credential that the gateway validated, such as two services that trust the same issuer.
  • Cloud provider credentials. The gateway authenticates as itself, using the identity of the workload it runs as. This is the method to reach for on a managed cluster, because it needs no stored secret: the cloud supplies the identity and the gateway exchanges it for a token. Each provider also accepts an explicit credential when the ambient identity is not the one you want.
  • Signed JWT. For an upstream that rejects durable credentials outright and wants a fresh keypair-signed JWT on each call. The Snowflake SQL API is the common example.
  • OAuth token exchange. Narrows or re-scopes the client’s credential. Use it when the client identity should reach the backend, but not the client’s original token, and when one authorization server can issue the new token.
  • Cross App Access. Token exchange across a trust boundary, using the OAuth Identity Assertion Authorization Grant. The identity provider that authenticated the user and the authorization server that guards the resource are different parties, so the gateway performs two exchanges and holds a client registration at each. For a single-leg exchange, use OAuth token exchange instead.

Two methods are not available everywhere. GitHub Copilot works in the standalone binary only, and Signed JWT arrived in 1.5.x. For the full matrix, see Method availability.

Combine methods

A policy sets at most one of the methods above. They are alternatives, not layers, and configuring two is rejected rather than applied in some order.

One mechanism is additive. A credentials list injects extra credentials, each to its own location, and it works either on its own or alongside a primary method. Use it for an upstream that wants two credentials on the same request, such as a bearer token and a subscription key.

Backend authentication and client authentication

The two directions interact in one way that is easy to miss: a client authentication policy removes the credential it validates.

A JWT, API key, or basic auth policy reads the client credential from a location, validates it, and then strips it from the request so the backend never sees it. That is usually what you want. It also means the credential is gone by the time backend authentication runs, which matters for two of the methods:

  • Passthrough puts it back. The method exists for exactly this reason. On a route with no client authentication policy, passthrough does nothing, because nothing removed the credential in the first place.
  • Token exchange and Cross App Access read the request. Both take the subject token from a location on the incoming request, defaulting to the Authorization header with a Bearer prefix. If a client authentication policy on the same route has already stripped that header, the exchange finds nothing to exchange.

Warning

Do not point a client authentication policy and a token exchange at the same location. The JWT policy validates the token and strips it, the exchange then has no subject token, and the request fails with a 400 and a body of invalid request. The policy status looks healthy, and the reason appears only in the gateway log at debug level.

debug http::auth::oauth oauth token exchange subject token missing source=Header { name: "authorization", prefix: Some("Bearer ") }

Any of the following fixes it.

  • Read the validated token instead of the header. Set the exchange’s subjectToken.source.expression to the jwt.rawToken.unredacted() CEL expression, which reads the token from the JWT policy’s own result rather than from the request.
  • Move one of the two locations. Read the client credential from a different header in the client authentication policy, or point subjectToken.source at wherever the credential actually is.
  • Keep the credential in place. Set preserveToken: true on the client authentication policy so that it leaves the validated token where it found it, and the exchange reads it as usual. The token then stays in the request for every policy that runs later, so prefer one of the other two options when only the exchange needs it.

The other methods do not read the client credential at all, so they compose with any client authentication policy without further thought.

Backend authentication is not authorization

Backend authentication decides what credential the gateway sends. It does not decide who is allowed through. A route that attaches a static key to every backend request still forwards every request that reaches it.

To decide which callers are allowed, and which tools or models they may reach, use an authorization policy alongside backend authentication. The two are complementary: authorization runs on the way in, backend authentication on the way out.

Configure backend authentication

In Kubernetes, backend authentication is the auth field of a backend policy. Three resources carry it, and they are not interchangeable.

Review the following example configuration.
# Attach a policy to a backend, a route, or a gateway.
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
spec:
  targetRefs:
  - group: agentgateway.dev
    kind: AgentgatewayBackend
    name: my-backend
  backend:
    auth:
      secretRef:
        name: my-credentials
---
# Or set the credential inline on the backend that uses it.
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
spec:
  policies:
    auth:
      secretRef:
        name: my-credentials
ResourceFieldMethods available
AgentgatewayPolicyspec.backend.authAll methods.
AgentgatewayBackendspec.policies.authAll methods.
AgentgatewayModelspec.policies.authAll methods except crossAppAccess and jwtSign.

Choose the AgentgatewayPolicy resource when one credential serves several backends, or when you want to attach the credential higher up, such as to a route or a gateway. Choose the inline spec.policies.auth field when the credential belongs to exactly one backend or model. For how the controller resolves a policy that targets more than one level, see Targeting and merging.

Important

A policy that targets an AgentgatewayBackend takes effect only if a route forwards traffic to that backend. If no route does, the policy reports Attached=False with the message Policy is not attached, and the gateway sends no credential. The backendRefs entry of the HTTPRoute must name the AgentgatewayBackend, not the Kubernetes Service behind it.

Where the credential comes from

Every method except key and passthrough reads its credential from a Kubernetes Secret, through a secretRef field. The default resolver reads a specific key from the Secret, and the key differs by method.

FieldKeys that the resolver reads
auth.secretRefAuthorization. Set secretRef.key to read a different key.
auth.aws.secretRefaccessKey and secretKey, plus sessionToken for temporary credentials.
auth.azure.secretRefclientID, tenantID, and clientSecret.
auth.gcp.secretRefcredentials.json. Set secretRef.key to read a different key.
auth.jwtSign.signingKeyRefsigningKey.

The Secret must be in the same namespace as the policy or backend that names it.

The cloud methods do not need a Secret at all. When you omit secretRef, the gateway uses the ambient identity of the pod that it runs in, such as a Google service account through Workload Identity on GKE, an IAM role for a service account on EKS, or an Azure workload identity on AKS. Running without a long-lived secret is the recommended setup for each cloud, and each provider page describes the resolution order that the gateway follows.

Next

Each method has its own page.

MethodPage
Static keys, Secrets, passthrough, and extra credentialsStatic keys and passthrough
AWS, Azure, and Google CloudCloud provider credentials
Signed JWTSigned JWT (jwtSign)
OAuth token exchangeOAuth token exchange
Cross App AccessCross App Access (ID-JAG)

For the client side of authentication, see JWT auth and API key auth. To control which callers are allowed through, see Authorization.

Method availability and field differences

The standalone binary and Kubernetes configure the same features, but they do not use the same field names, and in several places they do not use the same shape either. Expand the following section before you copy a configuration block from one mode to the other.

Compare the standalone binary and Kubernetes

Which methods each mode supports:

MethodStandaloneKubernetes
Static keykeykey or secretRef
Passthroughpassthroughpassthrough
AWSawsaws
Azureazureazure
Google Cloudgcpgcp
GitHub CopilotcopilotNot available
Signed JWTjwtSign, in 1.5.x and laterjwtSign, in 1.5.x and later
OAuth token exchangeoauthTokenExchangeoauthTokenExchange
Cross App AccesscrossAppAccesscrossAppAccess
Extra credentialscredentialscredentials

Where the two differ in shape:

ConcernStandaloneKubernetes
Field that holds the settingspolicies.backendAuthspec.backend.auth or spec.policies.auth
Static keykey.value, either inline or {file: <path>}key, an inline string
Credential from a SecretNot available. Read the value from a file instead.secretRef
Credential locationNested under the method, such as key.locationA sibling field, auth.location
Methods that accept locationEvery method that writes a credentialkey, secretRef, and passthrough only
Entry in the credentials listlocation and keylocation and secretRef
Google token typeaccessToken and idTokenAccessToken and IdToken
Azure credential sourceNested under explicitConfig, plus an implicit and a developerImplicit methodSet directly on azure, with no developerImplicit method
OAuth client authentication methodclientSecretBasic, clientSecretPost, and privateKeyJwtClientSecretBasic, ClientSecretPost, and PrivateKeyJwt
Signing key for jwtSignsigningKey, either the PEM text or {file: <path>}signingKeyRef, a Secret reference

The capitalization differences are enforced, not cosmetic. The standalone binary rejects AccessToken, and the custom resources reject accessToken. A wrong case fails validation rather than falling back to a default.

Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.