API key auth
API keys are secure, long-lived UUIDs that clients provide when they send a request to your service. You might use API keys in the following scenarios:
- You know the set of users that need access to your service. These users do not change often, or you have automation that easily generates or deletes the API key when the users do change.
- You want direct control over how the credentials are generated and expire.
API key auth in kgateway
The kgateway proxy comes with built-in API key auth support via the TrafficPolicy resource. To secure your services with API keys, first provide your kgateway proxy with your API keys in the form of Kubernetes secrets. Then in the TrafficPolicy resource, you refer to the secrets in one of two ways.
- Specify a label selector that matches the label of one or more API key secrets. Labels are the more flexible, scalable approach.
- Refer to the name and namespace of each secret.
The proxy matches a request to a route that is secured by the external auth policy. The request must have a valid API key in the api-key header to be accepted. You can configure the name of the expected header. If the header is missing, or the API key is invalid, the proxy denies the request and returns a 401 response.
The following diagram illustrates the flow:
sequenceDiagram
participant C as Client / Agent
participant AGW as Kgateway Proxy
participant K8s as K8s Secrets<br/>(API Keys)
participant Backend as Backend
C->>AGW: POST /api<br/>(no api-key header)
AGW->>AGW: API key auth check:<br/>No API key found
AGW-->>C: 401 Unauthorized<br/>"no API Key found"
Note over C,Backend: Retry with API key
C->>AGW: POST /api<br/>api-key: Bearer N2YwMDIx...
AGW->>K8s: Lookup referenced secret<br/>(by name or label selector)
K8s-->>AGW: Secret found
AGW->>AGW: Compare API key from<br/>request header vs secret
alt mode: Strict — Key valid
AGW->>Backend: Forward request
Backend-->>AGW: Response
AGW-->>C: 200 OK + Response
else Key invalid or missing
AGW-->>C: 401 Unauthorized
end
Before you begin
-
Follow the Get started guide to install kgateway.
-
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.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESSkubectl port-forward deployment/http -n kgateway-system 8080:8080
Set up API key auth
Store your API keys in a Kubernetes secret so that you can reference it in an TrafficPolicy resource.
-
From your API management tool, generate an API key. The examples in this guide use
N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy. -
Create a Kubernetes secret to store your API key.
kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: apikey namespace: kgateway-system labels: app: httpbin type: extauth.solo.io/apikey stringData: api-key: N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy EOF -
Verify that the secret is created. Note that the
data.api-keyvalue is base64 encoded.kubectl get secret apikey -n kgateway-system -o yaml -
Create an TrafficPolicy resource that configures API key authentication for all routes that the Gateway serves and reference the
apikeysecret that you created earlier. The following example uses theStrictvalidation mode, which requires requests to include a validAuthorizationheader to be authenticated successfully. For other common configuration examples, see Other configuration examples.kubectl apply -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: TrafficPolicy metadata: name: apikey-auth namespace: kgateway-system spec: targetRefs: - group: gateway.networking.k8s.io kind: Gateway name: http apiKeyAuth: secretRef: name: apikey EOF -
Send a request to the httpbin app without an API key. Verify that the request fails with a 401 HTTP response code.
curl -vi "${INGRESS_GW_ADDRESS}:8080/headers" -H "host: www.example.com"curl -vi "localhost:8080/headers" -H "host: www.example.com"Example output:
... < HTTP/1.1 401 Unauthorized HTTP/1.1 401 Unauthorized Client authentication failed ... -
Repeat the request. This time, you provide a valid API key in the
Authorizationheader. Verify that the request now succeeds.curl -vi "${INGRESS_GW_ADDRESS}:8080/headers" \ -H "host: www.example.com" \ -H "api-key: Bearer N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy"curl -vi "localhost:8080/headers" \ -H "host: www.example.com" \ -H "api-key: Bearer N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy"Example output:
... HTTP/1.1 200 OK < access-control-allow-credentials: true access-control-allow-credentials: true < access-control-allow-origin: * access-control-allow-origin: * < content-type: application/json; encoding=utf-8 content-type: application/json; encoding=utf-8 < content-length: 441 content-length: 441 < x-envoy-upstream-service-time: 13 x-envoy-upstream-service-time: 13 < server: envoy server: envoy { "headers": { "Accept": [ "*/*" ], "Host": [ "www.example.com" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Envoy-External-Address": [ "127.0.0.1" ], "X-Forwarded-For": [ "10.244.0.18" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "f64f1efa-1288-47d8-921f-4cb8f8deb96c" ] } } ...
Cleanup
You can remove the resources that you created in this guide.kubectl delete TrafficPolicy apikey-auth -n kgateway-system
kubectl delete secret apikey -n kgateway-systemOther configuration examples
Review other common configuration examples.
Label selectors
Refer to your API key secrets by using label selectors.
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: apikey-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
apiKeyAuth:
secretSelector:
matchLabels:
app: httpbin
EOFCustom header name
By default, kgateway reads the API key from the api-key header. Use keySources to specify a different header name.
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: apikey-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
apiKeyAuth:
secretRef:
name: apikey
keySources:
- header: X-API-KEY
EOFMultiple key sources
Configure multiple key sources. The gateway proxy checks them in order. If you define different types of key sources, the precedence is determined as follows:
- Header key sources take precedence over query parameter
- Query parameter key sources take precedence over cookie key sources
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: apikey-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
apiKeyAuth:
secretRef:
name: apikey
keySources:
- header: X-API-KEY
- query: api_key
- cookie: auth_token
EOFForward client ID header
Use clientIdHeader to forward the authenticated client identifier to the upstream service in a request header. This setup is useful for passing caller identity to backend services.
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: apikey-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
apiKeyAuth:
secretRef:
name: apikey
clientIdHeader: x-client-id
EOFForward credential to upstream
By default, the API key is stripped from the request before it is forwarded to the upstream. Set forwardCredential: true to preserve the API key in the upstream request.
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: apikey-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
apiKeyAuth:
secretRef:
name: apikey
forwardCredential: true
EOFDisable API key auth
Use disable to override an API key auth policy that is applied at a higher level in the hierarchy, such as a gateway-level policy, for a specific route.
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: apikey-auth-disable
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin
apiKeyAuth:
disable: {}
EOF