Passthrough auth
Passthrough authentication lets you delegate all authorization decisions to your own external auth server. The kgateway proxy forwards each incoming request to your auth server, which decides whether to allow or deny it. This approach is useful when you have custom authentication logic, an existing auth service you want to reuse, or compliance requirements that demand a centralized auth server.
About passthrough auth
The kgateway proxy integrates with external auth servers that implement the Envoy external authorization gRPC protocol. You configure the connection to your auth server in a GatewayExtension resource, and then reference that extension in a TrafficPolicy resource.
sequenceDiagram
participant C as Client
participant AGW as Kgateway Proxy
participant Auth as Auth Server
participant Backend as Backend
C->>AGW: HTTP Request
AGW->>Auth: Forward request for auth decision<br/>(gRPC ext_authz protocol)
alt Authorized
Auth-->>AGW: 200 OK (allow)
AGW->>Backend: Forward request
Backend-->>AGW: Response
AGW-->>C: Response
else Not Authorized
Auth-->>AGW: 403 Forbidden (deny)
AGW-->>C: 403 Forbidden
end
- The client sends a request to the kgateway proxy.
- The proxy forwards the request to your auth server using the Envoy gRPC external auth protocol.
- If the auth server allows the request, the proxy forwards it to the backend.
- If the auth server denies the request, the proxy returns the configured error status (default: 403 Forbidden) to the client.
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
Deploy your auth server
Deploy an auth server that implements the Envoy external auth gRPC protocol. The following example uses the Istio external authorization service for quick testing. This service allows requests that include the x-ext-authz: allow header and denies all others.
-
Deploy the auth server.
kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: ext-authz namespace: kgateway-system labels: app: ext-authz spec: replicas: 1 selector: matchLabels: app: ext-authz template: metadata: labels: app: ext-authz app.kubernetes.io/name: ext-authz spec: containers: - name: ext-authz image: gcr.io/istio-testing/ext-authz:1.25-dev ports: - containerPort: 9000 EOF -
Create a Service so that the proxy can reach the auth server.
kubectl apply -f - <<EOF apiVersion: v1 kind: Service metadata: name: ext-authz namespace: kgateway-system labels: app: ext-authz spec: ports: - port: 4444 targetPort: 9000 protocol: TCP appProtocol: kubernetes.io/h2c selector: app: ext-authz EOF -
Verify that the auth server pod is running.
kubectl get pods -n kgateway-system -l app=ext-authz
Set up passthrough auth
-
Create a GatewayExtension resource that points the proxy to your auth server. The GatewayExtension must be in the same namespace as the Service that backs the auth server, or you must set up a Kubernetes ReferenceGrant.
kubectl apply -f - <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: GatewayExtension metadata: name: passthrough-auth namespace: kgateway-system labels: app: ext-authz spec: type: ExtAuth extAuth: grpcService: backendRef: name: ext-authz port: 4444 EOF -
Create a TrafficPolicy that applies passthrough auth at the Gateway level. For other common configuration examples, see Other configuration examples.
kubectl apply -f - <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: TrafficPolicy metadata: name: passthrough-auth namespace: kgateway-system labels: app: ext-authz spec: targetRefs: - group: gateway.networking.k8s.io kind: Gateway name: http extAuth: extensionRef: name: passthrough-auth EOF -
Send a request without the required header. Verify that the auth server denies the request with a 403 response.
curl -i http://$INGRESS_GW_ADDRESS:8080/headers -H "host: www.example.com:8080"curl -i localhost:8080/headers -H "host: www.example.com"Example output:
HTTP/1.1 403 Forbidden x-ext-authz-check-result: denied ... denied by ext_authz for not found header `x-ext-authz: allow` in the request -
Send a request with the
x-ext-authz: allowheader. The Istio auth server is configured to allow requests with this header. Verify that the request succeeds.curl -i http://$INGRESS_GW_ADDRESS:8080/headers -H "host: www.example.com:8080" -H "x-ext-authz: allow"curl -i localhost:8080/headers -H "host: www.example.com" -H "x-ext-authz: allow"Example output:
HTTP/1.1 200 OK ...
Cleanup
You can remove the resources that you created in this guide.kubectl delete TrafficPolicy -A -l app=ext-authz
kubectl delete gatewayextension,deployment,service -n kgateway-system -l app=ext-authzOther configuration examples
Review other common configuration examples.
Disable passthrough auth for a specific route
Apply a passthrough auth policy at the Gateway level, then disable it for a specific HTTPRoute — for example, to exempt health-check endpoints.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: passthrough-auth-disable
namespace: httpbin
labels:
app: ext-authz
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin
extAuth:
disable: {}
EOFSend the request body to the auth server
By default, only request headers are forwarded to the auth server. Use withRequestBody to also buffer and send the request body. Note that buffering has performance implications for streaming requests.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: passthrough-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
extAuth:
extensionRef:
name: passthrough-auth
withRequestBody:
maxRequestBytes: 8192
EOFPass additional context to the auth server
Use contextExtensions to send additional key-value metadata to the auth server alongside the request. This setup is useful for passing policy identifiers or tenant information.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: passthrough-auth
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
extAuth:
extensionRef:
name: passthrough-auth
contextExtensions:
policy-id: "my-auth-policy"
tenant: "team-a"
EOFFail open
By default, if the auth server is unavailable, requests are denied. Set failOpen: true on the GatewayExtension to allow requests through when the auth server cannot be reached. Use this option with caution.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: passthrough-auth
namespace: kgateway-system
spec:
type: ExtAuth
extAuth:
failOpen: true
grpcService:
backendRef:
name: ext-authz
port: 4444
EOFCustom error status code
By default, the proxy returns a 403 Forbidden when the auth server denies a request. Use statusOnError on the GatewayExtension to return a different HTTP status code, such as 401 Unauthorized.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: passthrough-auth
namespace: kgateway-system
spec:
type: ExtAuth
extAuth:
statusOnError: 401
grpcService:
backendRef:
name: ext-authz
port: 4444
EOFCustom request timeout
Set a timeout for how long the proxy waits for the auth server to respond.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: passthrough-auth
namespace: kgateway-system
spec:
type: ExtAuth
extAuth:
grpcService:
backendRef:
name: ext-authz
port: 4444
requestTimeout: 5s
EOF