Upstream Authentication
Traefik Hub enables seamless upstream authentication to backend APIs using dedicated middleware configurations. This guide demonstrates how to implement common authentication patterns required when your backend APIs expect specific authentication credentials.
Understanding Upstream Authentication
Upstream authentication occurs when Traefik Hub automatically injects authentication credentials into requests before forwarding them to backend APIs. This pattern is essential when migrating from existing API platforms where backend services expect specific authentication formats.
The request flow in the context of upstream authentication is:
- Client authenticates to the gateway using an API key or a JWT (client authentication)
- Gateway authorizes the request based on configured policies (plans, subscriptions, RBAC)
- Gateway injects upstream credentials using Traefik Hub middlewares (Headers, Query Parameter, or OAuth Client Credentials)
- Backend service receives the request with the required upstream authentication
This approach decouples client authentication from upstream authentication, allowing you to maintain existing backend authentication requirements while providing a unified consumer experience.
Clients typically obtain their API key or JWT via the API Portal or an external IdP (for example, Okta or Keycloak). Those client credentials are used at the gateway (step 1) and are independent of the upstream credentials injected by the gateway (step 3).
Many Oracle deployments use a static service account identity for the gateway to authenticate to upstream services. The backend authorizes the gateway as the consumer and remains protected, even if clients are anonymous at the edge. The original caller’s identity is not propagated by the upstream authentication itself, but applications can carry user context in the request payload or headers as business data.
You can model a service account with:
- BasicAuth or an API key injected by the gateway
- OAuth 2.0 Client Credentials (gateway obtains and forwards an access token)
BasicAuth Pattern
BasicAuth upstream authentication injects HTTP Basic Authentication headers into requests before forwarding them to backend APIs. This pattern is commonly used with legacy APIs that expect traditional username/password authentication.
The Headers middleware handles BasicAuth by adding a static Authorization
header with Base64-encoded credentials.
- Middleware Configuration
- IngressRoute Integration
- Credential Generation
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-basicauth
namespace: apps
spec:
headers:
customRequestHeaders:
Authorization: "Basic YXBpLWNsaWVudDpzZWN1cmUtcGFzc3dvcmQ="
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: protected-api
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v1/users`)
kind: Rule
services:
- name: user-service
port: 8080
middlewares:
- name: upstream-basicauth
htpasswd -nbB api-client secure-password | base64
# Output: YXBpLWNsaWVudDokYXByMSRrMjNBcE13bSR5N0lZWjBMcThBVkdvMzJYcFNVdGMwCgo=
For quick testing, you can also use an online BasicAuth header generator: debugbear.com/basic-auth-header-generator.
Security Considerations
For production deployments, avoid hardcoded BasicAuth credentials in the Headers
middleware. Use a plugin that supports secret references,
or prefer OAuth Client Credentials when possible.
- Headers Middleware with static value
- Headers with secret value
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-basicauth
namespace: apps
spec:
headers:
customRequestHeaders:
Authorization: "Basic YXBpLWNsaWVudDpzZWN1cmUtcGFzc3dvcmQ="
This example uses the community Header transformation plugin (headerTransformation
), which can set request headers and supports URN
secret references.
- Secret
- Middleware
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: upstream-basicauth-secret
namespace: apps
stringData:
# Pre-compute the full Authorization header value or a token you want to inject
authorization: "Basic YXBpLWNsaWVudDpzZWN1cmUtcGFzc3dvcmQ="
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-basicauth-from-secret
namespace: apps
spec:
plugin:
headerTransformation:
Rules:
- Name: "Set Authorization"
Header: "Authorization"
Value: "urn:k8s:secret:upstream-basicauth-secret:authorization"
Type: "Set"
API Key Pattern
API Key authentication supports both header-based and query parameter-based implementations. The choice depends on how your backend API expects to receive the API key.
Header-Based API Key
Header-based API keys are transmitted through HTTP headers, typically using headers like X-API-Key
, X-API-Token
, or custom header names specified by the backend API.
- Standard API Key Header
- Custom Header Name
- Multiple Headers
- IngressRoute
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-api-key-header
namespace: apps
spec:
headers:
customRequestHeaders:
X-API-Key: "your-static-api-key-here"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-custom-header
namespace: apps
spec:
headers:
customRequestHeaders:
X-Custom-Auth-Token: "your-custom-token-here"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-multi-header
namespace: apps
spec:
headers:
customRequestHeaders:
X-API-Key: "your-api-key"
X-Client-ID: "your-client-id"
X-API-Version: "v1"
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-key-headers
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v1/param`)
kind: Rule
services:
- name: param-service
port: 8080
middlewares:
- name: upstream-api-key-header
- name: upstream-custom-header
- name: upstream-multi-header
Query Parameter-Based API Key
Query parameter-based API keys are appended to the request URL as query parameters. The Query Parameter middleware handles this pattern by injecting static API keys into the request URL.
- Set API Key Parameter
- Multiple Query Parameters
- Dynamic Parameter from Header
- IngressRoute
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-api-key-param
namespace: apps
spec:
plugin:
queryParam:
set:
- name: api_key
value: "your-static-api-key-here"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-multi-param
namespace: apps
spec:
plugin:
queryParam:
set:
- name: api_key
value: "your-api-key"
- name: client_id
value: "your-client-id"
- name: format
value: "json"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-dynamic-param
namespace: apps
spec:
plugin:
queryParam:
set:
- name: api_key
fromHeader: X-API-Key
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-key-headers
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v1/param`)
kind: Rule
services:
- name: param-service
port: 8080
middlewares:
- name: upstream-api-key-param
- name: upstream-multi-param
- name: upstream-dynamic-param
Securing API Keys
For production deployments, avoid hardcoded API keys. Here are some secure options available:
- Query Parameter with Secret
- Headers with secret value
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: upstream-api-keys
namespace: apps
stringData:
primary-api-key: "sk_live_abc123def456ghi789"
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-api-key-param-secure
namespace: apps
spec:
plugin:
queryParam:
set:
- name: api_key
value: "urn:k8s:secret:upstream-api-keys:primary-api-key"
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: upstream-api-keys
namespace: apps
stringData:
x-api-key: "sk_live_abc123def456ghi789"
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-header-key-from-secret
namespace: apps
spec:
plugin:
headerTransformation:
Rules:
- Name: "Set X-API-Key"
Header: "X-API-Key"
Value: "urn:k8s:secret:upstream-api-keys:x-api-key"
Type: "Set"
OAuth Client Credentials Pattern
OAuth Client Credentials flow provides token-based authentication for service-to-service communication. The OAuth 2.0 Client Credentials middleware automatically handles token acquisition, caching, and refresh cycles.
This pattern is ideal for backend APIs that require OAuth 2.0 access tokens and eliminates the complexity of manual token management.
Basic Configuration
- OAuth Middleware
- OAuth Credentials Secret
- IngressRoute with OAuth
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-oauth
namespace: apps
spec:
plugin:
oAuthClientCredentials:
url: https://auth.example.com/oauth/token
clientID: urn:k8s:secret:oauth-credentials:clientID
clientSecret: urn:k8s:secret:oauth-credentials:clientSecret
audience: https://api.example.com
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: oauth-credentials
namespace: apps
stringData:
clientID: "your-oauth-client-id"
clientSecret: "your-oauth-client-secret"
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: oauth-protected-api
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v1/data`)
kind: Rule
services:
- name: data-service
port: 8080
middlewares:
- name: upstream-oauth
Advanced OAuth Configuration
The OAuth middleware supports advanced features like token caching, custom claims validation, and header forwarding:
- Advanced OAuth Configuration
- Redis Cache Configuration
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-oauth-advanced
namespace: apps
spec:
plugin:
oAuthClientCredentials:
url: https://auth.example.com/oauth/token
clientID: urn:k8s:secret:oauth-credentials:clientID
clientSecret: urn:k8s:secret:oauth-credentials:clientSecret
audience: https://api.example.com
claims: Equals(`scope`, `read:data`)
forwardHeaders:
X-Token-Subject: sub
X-Token-Scope: scope
X-Token-Expires: exp
store:
redis:
endpoints: redis.traefik-hub.svc.cluster.local:6379
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: traefik-hub
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: traefik-hub
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
OAuth Token Lifecycle
The OAuth middleware handles the complete token lifecycle:
- Initial Token Request: Acquires access token using client credentials
- Token Caching: Stores valid tokens in Redis to reduce authorization server load
- Automatic Refresh: Requests new tokens before expiration
- Error Handling: Retries unsuccessful requests and handles authorization server errors
Combining Authentication Patterns
Complex scenarios may require multiple authentication mechanisms. Use middleware chaining to combine different upstream authentication patterns:
- Chain Middleware
- Custom Headers Middleware
- OAuth Client Credentials Middleware
- IngressRoute
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: multi-auth-chain
namespace: apps
spec:
chain:
middlewares:
- name: upstream-oauth
- name: upstream-custom-headers
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-custom-headers
namespace: apps
spec:
headers:
customRequestHeaders:
X-Service-Version: "v1"
X-Request-Source: "traefik-hub"
X-Forwarded-By: "api-gateway"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: upstream-oauth
namespace: apps
spec:
plugin:
oAuthClientCredentials:
url: https://auth.example.com/oauth/token
clientID: urn:k8s:secret:oauth-credentials:clientID
clientSecret: urn:k8s:secret:oauth-credentials:clientSecret
audience: https://api.example.com
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: multi-auth-chain
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v1/data`)
kind: Rule
services:
- name: data-service
port: 8080
middlewares:
- name: multi-auth-chain
Middleware chaining allows you to tailor upstream authentication to match each backend's specific requirements. The most common pattern combines OAuth token forwarding with custom headers, enabling you to send both a bearer token and additional metadata like service identifiers or request context.
Legacy systems sometimes require multiple authentication methods simultaneously. You can chain an OAuth middleware with an API key middleware to satisfy backends that expect both a bearer token and a static API key. While less common in modern architectures, this approach ensures compatibility with existing upstream services during migration.
Troubleshooting
When upstream authentication fails, Traefik Hub returns standardized HTTP error responses to clients while logging detailed diagnostic information. Understanding these error patterns helps identify and resolve configuration issues.
Real-World OAuth Error Scenario
This example demonstrates a complete OAuth upstream authentication error using GitHub's OAuth endpoint with intentionally wrong credentials, showing exactly what clients and administrators see.
Test Request and Client Response
# OAuth middleware configured with wrong credentials against GitHub's OAuth endpoint
curl -H "Host: whoami-oauth-test.localhost" http://localhost/ -v
# Client receives:
* Connected to localhost (::1) port 80
> GET / HTTP/1.1
> Host: whoami-oauth-test.localhost
> User-Agent: curl/8.7.1
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Tue, 12 Aug 2025 10:03:07 GMT
< Content-Length: 13
<
Unauthorized
Key observations:
- Client receives generic
401 Unauthorized
with minimal information - No indication of the specific authentication error
- Response includes security headers (
X-Content-Type-Options
)
Gateway Logs Analysis
Traefik Hub logs reveal the complete error chain, the ID of the cluster, the name of the middleware and the type of the middleware:
DBG Unable to get token error="unauthorized: oauth2: cannot fetch token: 401 UNAUTHORIZED Response: "
cluster_id=aebfc601-e306-4cfa-9f76-f5535b0fe16a
middlewareName=traefik-upstream-oauth-github-wrong@kubernetescrd
middlewareType=oAuthClientCredentials
Critical details in logs:
- Middleware identification:
upstream-oauth-github-wrong@kubernetescrd
helps locate the failing configuration - Error type:
oauth2: cannot fetch token: 401 UNAUTHORIZED
indicates credential rejection - No retries: OAuth server responds immediately with 401, no retry attempts occur
- Cluster context:
cluster_id
helps correlate logs in multi-cluster environments
Access Log Analysis
Traefik Hub access logs reveal the complete request flow and confirm the error occurred in middleware processing:
{
"ClientAddr":"10.42.0.1:55438",
"DownstreamStatus":401,
"Duration":522039148,
"OriginContentSize":0,
"OriginDuration":0,
"OriginStatus":0,
"Overhead":522039148,
"RequestHost":"whoami-oauth-test.localhost",
"RequestMethod":"GET",
"RequestPath":"/",
"RouterName":"traefik-whoami-oauth-upstream-test-3685623e73b09ae3ac3f@kubernetescrd"
}
Key access log indicators:
DownstreamStatus: 401
: Client receives 401 Unauthorized responseOriginStatus: 0
: Request never reached the backend serviceOriginDuration: 0
: Zero time spent communicating with backendDuration: 522039148
: Total request time (522ms)Overhead: 522039148
: All processing time consumed by middleware (no backend processing)
Common Error Patterns
DNS Resolution Errors
- Client sees:
401 Unauthorized
- Logs show: Multiple retry attempts with exponential backoff (1s, 2s, 4s intervals)
- Key indicators:
"no such host"
errors, 4 retry attempts before giving up
Wrong Credentials
- Client sees:
401 Unauthorized
(immediate response) - Logs show:
"401 UNAUTHORIZED Response"
from OAuth server - Key indicators: No retry attempts, immediate error.
Missing Kubernetes Secrets
- Client sees:
404 Not Found
(route fails to register) - Logs show:
"secret not found"
during middleware loading - Key indicators: Route configuration errors, middleware creation errors.
Debugging
-
Check client response:
401
suggests authentication issues,404
suggests configuration problems,500
suggests middleware errors. -
Examine gateway logs: Filter for your middleware name and look for error patterns:
kubectl logs -n traefik deployment/traefik | grep "middlewareName=your-middleware-name"
-
Verify secret references: Ensure Kubernetes Secrets exist and contain expected keys:
kubectl get secret your-secret-name -o yaml
kubectl describe secret your-secret-name -
Test OAuth endpoints manually: Validate OAuth server connectivity and credentials:
curl -X POST https://auth.example.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=test&client_secret=test" -
Enable access and debug logging to track request patterns and response codes:
logs:
general:
level: DEBUG
access:
enabled: true
format: json
Successful upstream authentication shows the injected headers in backend logs, while failures show missing authentication context.
Conclusion
This guide provides the foundation for implementing upstream authentication patterns with Traefik Hub. Each pattern can be adapted to specific backend API requirements while maintaining security best practices and operational simplicity.