For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Static keys and passthrough
Send a static credential to a backend, forward the credential that the client sent, or add extra credentials to the request.
About
Use one of the following backend authentication methods to send a static credential to your backend. The client may already send the credential that the backend expects. If it does not, the gateway must supply one of its own.
- Kubernetes Secret (
secretRef) reads the credential from a Secret in the cluster. Use this method for an API key or a long-lived token. - Inline (
key) holds the credential in the policy itself. The value is stored in plain text in the cluster and in any Git repository that tracks the resource, so use a Secret instead wherever you can. - Passthrough (
passthrough) forwards the JWT that the client sent. Use this method when the backend validates the same token that the gateway validated.
All three write the credential to the Authorization header with a Bearer prefix by default. The location field changes where the gateway writes it.
The credentials list is separate. It adds credentials rather than choosing one, so you can send a second or third credential on the same request. Set it on its own, or alongside one of the three methods.
Before you begin
Follow the Get started guide to install agentgateway.
Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.
Get the external address of the gateway and save it in an environment variable.
Tip
Kind cluster? Kind does not support
LoadBalancerservices by default. To use this option with a Kind cluster, install and runcloud-provider-kind.export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
Send a static credential from a Secret
Create a Secret that holds the credential. The default resolver reads the
Authorizationkey.kubectl create secret generic backend-api-key \ --namespace httpbin \ --from-literal=Authorization="my-backend-token"Create an AgentgatewayPolicy that reads the Secret and attaches the credential to every request that the gateway forwards to the httpbin route.
kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayPolicy metadata: name: static-backend-auth namespace: httpbin spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: httpbin backend: auth: secretRef: name: backend-api-key EOFReview the following table to understand this configuration. The example sets
secretRef.nameonly. The remaining fields are optional: you add thesecretRef.*fields to the samesecretRefblock, andlocationalongside it.Field Description secretRef.nameRequired name of a Secret in the same namespace as the policy. secretRef.keyKey in the Secret that holds the credential. Defaults to Authorization.secretRef.groupandsecretRef.kindCredential source other than a Secret. Omit both to use a Secret. Set both together, because setting one alone is rejected. locationWhere the gateway writes the credential. Defaults to the Authorizationheader with aBearerprefix. Set exactly one ofheader,queryParameter, orcookie. For an example, see Change the credential location.Send a request through the gateway to the httpbin
/headersendpoint, which reflects the headers that the backend received.curl -s "http://$INGRESS_GW_ADDRESS:80/headers" -H "host: www.example.com" | jq '.headers.Authorization'The backend receives the value from the Secret, with the
Bearerprefix that the default location adds.[ "Bearer my-backend-token" ]
Warning
Store the bare token in the Secret. The gateway strips a Bearer prefix only when it reads the Authorization key, and then re-adds the prefix that the location defines. A value of Bearer my-backend-token under that key therefore still arrives as Bearer my-backend-token. Under any other key the prefix is not stripped, so the same value arrives as Bearer Bearer my-backend-token. Entries in the credentials list are never stripped, whichever key they read.
Send an inline credential
The key method holds the credential in the policy instead of a Secret. The value is stored in plain text in the cluster, and in any Git repository that tracks the resource. Use the method only when a Secret is not an option.
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
name: inline-backend-auth
namespace: httpbin
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin
backend:
auth:
key: my-backend-tokenThe value is a plain string, not a nested object, and it is capped at 2048 characters. The key method takes the same location field as secretRef and writes to the Authorization header with a Bearer prefix by default. Unlike secretRef, it never strips a Bearer prefix from the value that you set, so store the bare token here too.
Change the credential location
Set the location field in your AgentgatewayPolicy resource to write the credential somewhere other than the Authorization header. The field is a sibling of key, secretRef, and passthrough, not a field inside them, and it applies to those three methods only.
Update the policy to send the credential as an
x-api-keyheader instead.kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayPolicy metadata: name: static-backend-auth namespace: httpbin spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: httpbin backend: auth: secretRef: name: backend-api-key location: header: name: x-api-key EOFSend another request and check the new header.
curl -s "http://$INGRESS_GW_ADDRESS:80/headers" -H "host: www.example.com" | jq '.headers'The credential moves to
x-api-key, and the gateway adds no prefix. A custom location writes the bare value, because theBearerprefix belongs to the default location and not to the credential.{ "X-Api-Key": [ "my-backend-token" ], ... }To write a prefix at a custom header, set it explicitly.
location: header: name: x-api-key prefix: "Token "
Pass through client credentials
If the client already sends the credential that the backend expects, forward it with the passthrough method. A client authentication policy strips the credential that it validates before the gateway forwards the request, so without passthrough the backend receives nothing.
The method forwards a JWT only. It re-sends the token that a JWT authentication policy validated on the route. An API key or basic auth credential is still stripped, and passthrough does not add it back.
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
name: passthrough-backend-auth
namespace: httpbin
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin
backend:
auth:
passthrough: {}Note
On a route with no JWT authentication policy, passthrough sends nothing, because no validated token exists for the gateway to re-add. If the route has an API key or a basic auth policy instead, that credential is stripped and passthrough does not restore it.
The passthrough method has no field for where to read the credential from, because the gateway does not read it from the request at all. It re-sends the token that the JWT authentication policy already validated. The source is therefore wherever that policy’s own location field reads from, which is the Authorization header by default.
The location field on passthrough controls only where the gateway writes the token on the backend request. That location does not have to be where the client sent it. To read a JWT from the Authorization header and forward it as an x-forwarded-token header, set location to that header.
Note
Prefer passthrough over the preserveToken field of the JWT authentication policy. Both get the token to the backend. However, preserveToken leaves the token in its original location, where every policy that runs later can read it. The passthrough method re-adds the token only on the request that the gateway forwards to the backend.
Send more than one credential
Use the credentials list when a backend wants two credentials on the same request, such as a bearer token and a subscription key. The list does not replace the methods in the previous sections, and it is not how you choose one of them. The list is additive. Each entry names a Secret and a location, and the gateway sends every entry in it. If the policy also sets a primary method, the gateway sends that credential too.
The following example keeps secretRef as the primary credential and adds two more credentials from a second Secret. The primary credential still goes to the Authorization header. Each entry in the list carries its own location, and the policy-level location field does not apply to the list.
Create a Secret with two more credentials in it.
kubectl create secret generic extra-credentials \ --namespace httpbin \ --from-literal=tenant-key="my-tenant-key" \ --from-literal=subscription-key="my-subscription-key"Update the policy to send all three credentials.
Review the following table to understand this configuration.kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayPolicy metadata: name: static-backend-auth namespace: httpbin spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: httpbin backend: auth: secretRef: name: backend-api-key credentials: - location: header: name: x-tenant-key secretRef: name: extra-credentials key: tenant-key - location: queryParameter: name: subscription secretRef: name: extra-credentials key: subscription-key EOFField Description credentials[].locationRequired location that the gateway writes this credential to. Set exactly one of header,queryParameter, orcookie. Each entry carries its own location, and the policy-levellocationfield does not apply to the list.credentials[].secretRef.nameRequired name of a Secret in the same namespace as the policy. credentials[].secretRef.keyKey in the Secret that holds the credential. Defaults to Authorization, so set it for every entry that reads a Secret with more than one key in it. Unlike the primarysecretRef, an entry in the list never strips aBearerprefix from the value, whichever key it reads.Send a request to the httpbin
/getendpoint, which reflects the query string as well as the headers.curl -s "http://$INGRESS_GW_ADDRESS:80/get" -H "host: www.example.com" | jq '{headers, args}'The backend receives the primary credential in the
Authorizationheader, one extra credential as a header, and the other as a query parameter.{ "headers": { "Authorization": [ "Bearer my-backend-token" ], "X-Tenant-Key": [ "my-tenant-key" ], ... }, "args": { "subscription": [ "my-subscription-key" ] } }
The credentials list also works on its own, or alongside any other primary method. Omit secretRef and the gateway sends only the entries in the list. Set passthrough instead and the gateway forwards the client’s JWT alongside them.
Troubleshoot
| Symptom | Cause |
|---|---|
The backend receives no credential, and the policy reports Attached=False with Policy is not attached. | The policy targets an AgentgatewayBackend that no route forwards to. Point the backendRefs entry of the HTTPRoute at the AgentgatewayBackend, or target the HTTPRoute instead. |
The backend receives Bearer Bearer <token>. | The Secret value carries a Bearer prefix, and secretRef.key names a key other than Authorization. The gateway strips the prefix only from the default key. Store the bare token. |
The API server rejects the policy with location may only be set for key, secretRef, or passthrough auth. | The policy sets location next to a cloud method or a token exchange method. Those methods carry their own location field, or write to a fixed location. |
The API server rejects the policy with at most one of the fields in [key secretRef passthrough ...] may be set. | The policy sets two primary methods. Only the credentials list can be combined with a primary method. |
Cleanup
You can remove the resources that you created in this guide.kubectl delete AgentgatewayPolicy static-backend-auth -n httpbin
kubectl delete secret backend-api-key extra-credentials -n httpbin