Authentication
Inference Gateway supports authentication through OpenID Connect (OIDC), allowing you to secure your API with various identity providers. This guide focuses on setting up authentication with Keycloak, a popular open-source identity and access management solution.
Overview
When authentication is enabled, all requests to the Inference Gateway API must include a valid JWT token in the Authorization header. This token is issued by your configured identity provider (IdP) and is validated by Inference Gateway to authenticate requests.
Authentication Flow
- Users authenticate with the identity provider (Keycloak)
- The identity provider issues a JWT token
- Client applications include this token in requests to Inference Gateway
- Inference Gateway validates the token with the identity provider
- If valid, the request is processed; otherwise, a 401 Unauthorized response is returned
Configuration
To enable authentication on the Go gateway (inference-gateway/inference-gateway), set:
AUTH_ENABLE=true
AUTH_OIDC_ISSUER=https://your-keycloak-instance/realms/your-realm
AUTH_OIDC_CLIENT_ID=your-client-id
AUTH_OIDC_CLIENT_SECRET=your-client-secretThe rest of this page documents the Go gateway. For agents built with the TypeScript ADK, the same OIDC contract applies but the env-var names are different - see the cross-reference below.
Env-var naming: Go gateway vs. TypeScript ADK
The Go gateway and the TypeScript ADK ship separately and each pins its own canonical config struct, so the env-var names differ even though the underlying OIDC flow is identical. Use the column that matches whichever surface you're configuring - don't share an .env between them without translating.
| Setting | Go gateway | TypeScript ADK (details) |
|---|---|---|
| Enable / disable | AUTH_ENABLE | AUTH_ENABLE |
| OIDC issuer URL | AUTH_OIDC_ISSUER | AUTH_ISSUER_URL |
OAuth2 client id (aud) | AUTH_OIDC_CLIENT_ID | AUTH_CLIENT_ID |
| OAuth2 client secret | AUTH_OIDC_CLIENT_SECRET | AUTH_CLIENT_SECRET |
Both surfaces verify Bearer tokens against the issuer's JWKS, reject unauthenticated requests with HTTP 401 + WWW-Authenticate: Bearer, and keep their respective health endpoints public. The TypeScript ADK additionally returns a JSON-RPC -32001 envelope on the JSON-RPC endpoint and leaves /.well-known/agent-card.json public so A2A clients can negotiate auth from the advertised security scheme.
Keycloak Integration
This section provides a detailed guide for integrating Keycloak with Inference Gateway.
Prerequisites
- Keycloak server (v24.0.0 or later recommended)
- Inference Gateway (v0.23.1 or later)
- kubectl for Kubernetes deployment
- Task (optional, for running example tasks)
Setting Up Keycloak
Option 1: Using the Authentication Example
Inference Gateway provides a complete example for setting up Keycloak authentication in a Kubernetes environment:
Clone the repository:
bashgit clone https://github.com/inference-gateway/inference-gateway.git cd inference-gateway/examples/kubernetes/authenticationDeploy the infrastructure (Keycloak, PostgreSQL, etc.):
bashtask deploy-infrastructureDeploy Inference Gateway with authentication enabled:
bashtask deploy-inference-gatewayGet the Keycloak admin password:
bashtask keycloak-admin-passwordAccess the Keycloak admin console:
- URL:
https://keycloak.inference-gateway.local - Username:
temp-admin - Password: (output from the previous command)
- URL:
Test the authentication:
bashcurl -k -v -H "Authorization: Bearer $(task fetch-access-token)" https://api.inference-gateway.local/v1/models
Option 2: Manual Setup
If you're setting up Keycloak manually, follow these steps:
Install Keycloak: Follow the official Keycloak installation guide for your environment.
Create a Realm:
- Log in to the Keycloak Admin Console
- Click "Create Realm"
- Enter "inference-gateway-realm" as the realm name
- Click "Create"
Create a Client:
- In your realm, go to "Clients" → "Create client"
- Client ID:
inference-gateway-client - Client Authentication: Enabled
- Save the client
- On the client settings page:
- Access Type: confidential
- Service Account Enabled: ON
- Save the changes
Get Client Credentials:
- Go to the "Credentials" tab of your client
- Copy the "Client Secret"
Create Test User (optional):
- Go to "Users" → "Add user"
- Username:
user - Email:
[email protected] - Email Verified: ON
- Save
- Go to "Credentials" tab
- Set password:
password - Temporary: OFF
- Save
Configure Inference Gateway
Update your Inference Gateway configuration to enable authentication:
Using Environment Variables
AUTH_ENABLE=true
AUTH_OIDC_ISSUER=https://your-keycloak-instance/realms/inference-gateway-realm
AUTH_OIDC_CLIENT_ID=inference-gateway-client
AUTH_OIDC_CLIENT_SECRET=your-client-secretUsing Kubernetes ConfigMap and Secret
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: inference-gateway
namespace: inference-gateway
data:
AUTH_ENABLE: 'true'
AUTH_OIDC_ISSUER: https://your-keycloak-instance/realms/inference-gateway-realm
---
# Secret
apiVersion: v1
kind: Secret
metadata:
name: inference-gateway
namespace: inference-gateway
stringData:
AUTH_OIDC_CLIENT_ID: inference-gateway-client
AUTH_OIDC_CLIENT_SECRET: your-client-secret
type: OpaqueObtaining Access Tokens
To access the protected API, you need to obtain a JWT token from Keycloak:
Password Grant Flow (Testing Only)
curl -k -s -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
"https://your-keycloak-instance/realms/inference-gateway-realm/protocol/openid-connect/token" \
-d "grant_type=password" \
-d "client_id=inference-gateway-client" \
-d "client_secret=your-client-secret" \
-d "username=user" \
-d "password=password" | jq -r .access_tokenClient Credentials Flow (Service-to-Service)
curl -k -s -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
"https://your-keycloak-instance/realms/inference-gateway-realm/protocol/openid-connect/token" \
-d "grant_type=client_credentials" \
-d "client_id=inference-gateway-client" \
-d "client_secret=your-client-secret" | jq -r .access_tokenMaking Authenticated Requests
Once you have the token, include it in the Authorization header:
curl -H "Authorization: Bearer YOUR_TOKEN" https://your-inference-gateway/v1/modelsSelf-Signed Certificates
When working with self-signed certificates (common in development environments), you need to make Inference Gateway trust the Keycloak certificate.
Create a ConfigMap holding the issuer's CA certificate:
kubectl create configmap keycloak-ca \
-n inference-gateway \
--from-literal=ca.crt="$(kubectl get secret keycloak-tls -n idp -o jsonpath='{.data.ca\.crt}' | base64 -d)"Then reference it from the Kubernetes Operator: set spec.auth.oidc.caCertRef to the ConfigMap key holding the PEM CA, and the operator mounts the certificate into the gateway pod and points SSL_CERT_FILE at it for you - no need to wire it by hand.
Best Practices
- Use HTTPS: Always secure both your Keycloak and Inference Gateway instances with HTTPS.
- Token Validation: Inference Gateway validates tokens with the OIDC issuer, ensuring they are legitimate.
- Secret Management: Store sensitive information like client secrets using secure methods (e.g., Kubernetes Secrets, HashiCorp Vault).
- Client Roles: Configure client roles in Keycloak to implement fine-grained access control.
- Token Expiry: Configure appropriate token lifetimes in Keycloak based on your security requirements.
Troubleshooting
Common Issues
401 Unauthorized Errors:
- Check that the token hasn't expired
- Verify that AUTH_OIDC_ISSUER is correct
- Ensure the client secret is valid
Certificate Issues:
- When using self-signed certificates, ensure Inference Gateway trusts Keycloak's certificate
- Set
SSL_CERT_FILEto point to the certificate location
Clock Skew:
- Ensure server clocks are synchronized as JWT validation is time-sensitive
Next Steps
After setting up authentication, consider:
- Implementing Role-Based Access Control (RBAC) in Keycloak
- Configuring token exchange for service-to-service communication
- Setting up multi-factor authentication for enhanced security
- Protecting an agent built on the TypeScript ADK with the same OIDC issuer (note the different env-var names)
- Managing the gateway and its OIDC settings declaratively with the Kubernetes Operator via
spec.auth.oidc
