For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
OAuth2 and OIDC
Secure your services by delegating authentication to an external Identity Provider (IdP) using OpenID Connect (OIDC) or OAuth 2.0.
About OAuth2 and OIDC in kgateway
When you configure OAuth2/OIDC in kgateway, the gateway proxy acts as the OAuth2 client. It intercepts incoming client requests, determines if they are authenticated, and handles the handshake with the authorization server:
- Redirect: If the request does not contain valid session cookies, the gateway redirects the client’s browser to the IdP’s authorization endpoint.
- Callback: After the user successfully authenticates with the IdP, they are redirected back to the gateway’s redirect URI with an authorization code.
- Token Exchange: The gateway proxy intercepts the redirect callback, contacts the IdP’s token endpoint to exchange the authorization code for access, ID, and refresh tokens.
- Cookies & Forwarding: The gateway proxy stores the received tokens in encrypted, secure, HTTP-only session cookies in the user’s browser, and then forwards the authenticated request to the upstream backend. Subsequent requests from the client use these cookies to bypass the authorization handshake.
The following sequence diagram illustrates this authorization code flow:
sequenceDiagram
autonumber
participant Client as User Browser
participant Gateway as kgateway proxy
participant IdP as Identity Provider (such as Keycloak)
participant Backend as Upstream Service
Client->>Gateway: 1. Request /api (no session cookies)
Gateway-->>Client: 2. 302 Redirect to IdP Auth Endpoint
Client->>IdP: 3. Login with Credentials
IdP-->>Client: 4. 302 Redirect to Redirect URI with Auth Code
Client->>Gateway: 5. Callback request with Auth Code
Gateway->>IdP: 6. POST /token (exchange code for tokens)
IdP-->>Gateway: 7. ID, Access, & Refresh Tokens
Gateway-->>Client: 8. 302 Redirect to original path + set session cookies
Client->>Gateway: 9. Request /api with session cookies
Gateway->>Backend: 10. Forward request to upstream
Backend-->>Gateway: 11. Response
Gateway-->>Client: 12. 200 OK + Response
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_ADDRESS
This guide requires an OIDC IdP, such as Keycloak, deployed in-cluster and reachable, and an HTTPRoute for your app.
Set up Keycloak as the identity provider
This guide uses Keycloak as the example IdP. Follow these steps to deploy and configure it.
1. Create the Keycloak admin secret
Store the admin credentials in a Kubernetes Secret:
kubectl apply -f- <<EOF
apiVersion: v1
kind: Secret
metadata:
name: keycloak-admin
namespace: keycloak-system
type: Opaque
stringData:
admin-user: admin
admin-password: admin
EOF2. Deploy Keycloak
Choose one of the following methods:
Option A: Using Helm (recommended for production):
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install keycloak bitnami/keycloak \
--namespace keycloak-system \
--create-namespace \
--set auth.adminUser=admin \
--set auth.adminPassword=admin \
--set service.type=ClusterIP \
--set service.ports.http=8080This deploys Keycloak with the admin credentials admin/admin.
Option B: Using YAML (for testing, no Helm required):
kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
namespace: keycloak-system
spec:
replicas: 1
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:latest
args: ["start-dev", "--http-port=8080"]
env:
- name: KEYCLOAK_ADMIN
valueFrom:
secretKeyRef:
name: keycloak-admin
key: admin-user
- name: KEYCLOAK_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak-admin
key: admin-password
ports:
- containerPort: 8080
EOF3. Expose Keycloak as a service
If you used the YAML method in step 2, expose Keycloak as a service:
kubectl apply -f- <<EOF
apiVersion: v1
kind: Service
metadata:
name: keycloak
namespace: keycloak-system
spec:
selector:
app: keycloak
ports:
- port: 8080
targetPort: 8080
EOFIf you used the Helm method, a service is automatically created. Skip this step.
4. Port-forward Keycloak
kubectl port-forward svc/keycloak -n keycloak-system 8080:80805. Configure Keycloak
- Access the admin console at
http://localhost:8080. - Log in with:
- Username:
admin - Password:
admin
- Username:
- Create a new realm (e.g.,
kgateway). - Create a confidential client:
- Set Valid Redirect URIs to
https://www.example.com/oauth2/redirect. - Note the client ID and client secret for the next section.
- Set Valid Redirect URIs to
For more details, see the Keycloak documentation.
Set up OAuth2/OIDC authentication
To configure OIDC/OAuth2, you store the client credentials in a Kubernetes Secret, create a GatewayExtension specifying the provider details, and apply the policy using a TrafficPolicy.
1. Store client secret in a Secret
Create a Kubernetes Secret containing your OAuth2 client secret. The secret must contain the client secret under the client-secret key:
kubectl apply -f- <<EOF
apiVersion: v1
kind: Secret
metadata:
name: oauth2-client-secret
namespace: kgateway-system
type: Opaque
stringData:
client-secret: my-super-secret-client-secret-key
EOFmy-super-secret-client-secret-key with the OAuth/OIDC client secret from your identity provider. For example, in Keycloak, this is the secret generated for your confidential client when you create it in the Keycloak admin console.2. Create a GatewayExtension for OAuth2
Create a GatewayExtension specifying your OIDC provider settings in the spec.oauth2 block. The following example uses Keycloak as the Identity Provider:
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: keycloak-oauth2
namespace: kgateway-system
spec:
oauth2:
backendRef:
name: keycloak
namespace: keycloak-system
port: 8080
issuerURI: https://keycloak.example.com/realms/master
redirectURI: https://www.example.com/oauth2/redirect
credentials:
clientID: my-client-id
clientSecretRef:
name: oauth2-client-secret
scopes:
- openid
- email
- profile
EOF| Setting | Description |
|---|---|
backendRef | Reference to the Kubernetes Service representing your Identity Provider (IdP). This is the internal network path the gateway uses to communicate with the IdP. |
issuerURI | The public issuer URL of the OpenID provider used to discover the auth, token, and JWKS endpoints. Note that while backendRef points to the in-cluster location for direct networking, issuerURI represents the identity of the issuer as seen by the browser or external clients. |
redirectURI | The callback URI registered with your IdP. The gateway intercepts this endpoint to complete the code exchange. |
credentials.clientID | The client ID registered with your IdP. |
credentials.clientSecretRef | Reference to the Kubernetes Secret containing the client secret. |
scopes | The scopes requested in the authentication flow. Include openid to enable OpenID Connect. |
For more details, see the API reference.
3. Create a TrafficPolicy
Enforce the OAuth2/OIDC authentication policy on your Gateway using the oauth2 configuration block in a TrafficPolicy:
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
name: oauth2-auth-policy
namespace: kgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
oauth2:
extensionRef:
name: keycloak-oauth2
EOF| Setting | Description |
|---|---|
targetRefs | Selects the resource to apply the authentication policy to (such as a Gateway or HTTPRoute). |
oauth2.extensionRef | References the GatewayExtension created in the previous step. |
Verify the authentication flow
- Open your browser and navigate to the application URL (e.g.,
https://www.example.com/).
- Verify that you are redirected to the Keycloak login screen.
-
Authenticate with your credentials.
-
Verify that you are redirected back to your application and the request succeeds.
- Inspect the cookies in your browser; you should see secure, HTTP-only cookies containing the session tokens.
Test with curl
The following examples show how to test the OAuth2/OIDC flow using curl. The first request triggers a redirect to the IdP, and the second request uses the session cookie obtained after browser login.
Send a request without authentication (browser flow):
curl -vik http://$INGRESS_GW_ADDRESS:8080/headers -H "host: www.example.com:8080"Expected output:
< HTTP/1.1 302 Found
< location: https://keycloak.example.com/realms/master/protocol/openid-connect/auth?...Send a request with session cookies (after browser login):
After completing the browser login flow, copy the session cookie from your browser’s developer tools (Application → Cookies) and replace session-cookie=... with the actual cookie value.
curl -vik http://$INGRESS_GW_ADDRESS:8080/headers \
-H "host: www.example.com:8080" \
--cookie "session-cookie=..."Expected output:
< HTTP/1.1 200 OKOptional: Test JWT bearer authentication for API clients
If you want to test with a bearer token (for API clients), you can use:
curl -vik http://$INGRESS_GW_ADDRESS:8080/headers \
-H "host: www.example.com:8080" \
--header "Authorization: Bearer $TOKEN"Expected output:
< HTTP/1.1 200 OKAdvanced configurations
Review these optional configurations to customize the OAuth2/OIDC behavior. Each of the following examples re-applies the GatewayExtension that you created in step 2 with an additional spec.oauth2 field. Because the resource name is unchanged, re-applying updates your existing GatewayExtension.
Forward access token to backend
By default, the gateway proxy stores tokens in cookies and does not forward them to backend services. Set forwardAccessToken: true in your GatewayExtension to forward the access token upstream in the Authorization: Bearer <token> header:
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: keycloak-oauth2
namespace: kgateway-system
spec:
oauth2:
backendRef:
name: keycloak
namespace: keycloak-system
port: 8080
issuerURI: https://keycloak.example.com/realms/master
redirectURI: https://my-app.example.com/oauth2/redirect
credentials:
clientID: my-client-id
clientSecretRef:
name: oauth2-client-secret
scopes:
- openid
- email
- profile
forwardAccessToken: true
EOFCustomize cookie configuration
You can customize the names, domain, and sameSite policy of the cookies used to store session tokens:
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: keycloak-oauth2
namespace: kgateway-system
spec:
oauth2:
backendRef:
name: keycloak
namespace: keycloak-system
port: 8080
issuerURI: https://keycloak.example.com/realms/master
redirectURI: https://my-app.example.com/oauth2/redirect
credentials:
clientID: my-client-id
clientSecretRef:
name: oauth2-client-secret
scopes:
- openid
- email
- profile
cookies:
domain: example.com
sameSite: Lax
names:
accessToken: my-custom-access-token
idToken: my-custom-id-token
EOFExtract JWT claims to custom request headers
If your Identity Provider issues tokens in JWT format, you can configure kgateway to verify the signatures and copy specific claims (such as the user email, sub, or custom roles) directly into HTTP headers forwarded to the backend:
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: keycloak-oauth2
namespace: kgateway-system
spec:
oauth2:
backendRef:
name: keycloak
namespace: keycloak-system
port: 8080
issuerURI: https://keycloak.example.com/realms/master
redirectURI: https://my-app.example.com/oauth2/redirect
credentials:
clientID: my-client-id
clientSecretRef:
name: oauth2-client-secret
scopes:
- openid
- email
- profile
jwt:
jwksURI: https://keycloak.example.com/realms/master/protocol/openid-connect/certs
idToken:
claimsToHeaders:
- name: sub
header: x-user-id
- name: email
header: x-user-email
EOFDeny redirect for AJAX / API requests
For API calls or AJAX requests (such as fetch or XMLHttpRequest), a 302 Redirect back to a login screen is undesirable. Use denyRedirect to specify header match rules. When a request matches these rules, the gateway returns a 401 Unauthorized response instead of redirecting:
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
name: keycloak-oauth2
namespace: kgateway-system
spec:
oauth2:
backendRef:
name: keycloak
namespace: keycloak-system
port: 8080
issuerURI: https://keycloak.example.com/realms/master
redirectURI: https://my-app.example.com/oauth2/redirect
credentials:
clientID: my-client-id
clientSecretRef:
name: oauth2-client-secret
scopes:
- openid
- email
- profile
denyRedirect:
headers:
- name: X-Requested-With
value: XMLHttpRequest
EOFCleanup
You can remove the resources that you created in this guide.kubectl delete TrafficPolicy oauth2-auth-policy -n kgateway-system
kubectl delete gatewayextension keycloak-oauth2 -n kgateway-system
kubectl delete secret oauth2-client-secret -n kgateway-system