OAuth 2.1 Client Credentials Authentication
The OAuth2 Client Credentials protocol (defined in OAuth 2.1 IETF DRAFT, section 4.2 & OAuth 2.0, RFC 6749, section 4.4) provides a way to secure delegated access between applications with a JWT access token.
With Traefik Hub, the authentication can be achieved either at the client level or at the gateway level.
Application Level
In this mode, every application brings its credentials (ClientId and ClientSecret) to Hub API Gateway using the Authorization header.
Then, Hub Gateway API calls the Identity Provider providing the application credentials to get the AccessToken as described in the diagram below.
To allow the OAuth2 Client Credential Middleware to use the credentials provided by the requests, apply the following configuration:
- Middleware OAuth2 Client Credentials
- IngressRoute
- Service & Deployment
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oauth2-client-creds
namespace: apps
spec:
plugin:
# Middleware minimal configuration
oAuthClientCredentials:
# IdP URL to get the access token
url: http://myidp:4444/oauth2/token
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: secure-applications-apigateway-oauth2-client-credentials
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Path(`/my-app`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: oauth2-client-creds
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
namespace: apps
spec:
replicas: 3
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami
---
apiVersion: v1
kind: Service
metadata:
name: whoami
namespace: apps
spec:
ports:
- port: 80
name: whoami
selector:
app: whoami
How to provide the credentials to the gateway?
To use the middleware at the application level, you need to provide the credentials to Hub using the Authorization header as described below:
# $client_id: your ClientID
# $client_secret: your client secret
# base64 encode the credentials
auth=$(echo -n "$client_id:$client_secret" | base64 -w 0)
# Use the Authorizarion Header to provide the credentials
curl -H "Authorization: Basic $auth" https://mydomain/my-app
Gateway level
In this mode, the credentials (ClientId and ClientSecret) are provided to the Hub API Gateway using the Middleware configuration. The applications that reach Hub API Gateway don't need to be authenticated. Hub API Gateway adds the credentials to the request headers and sends them to the Identity Provider, as described in the diagram below:
To allow the OAuth2 Client Credential Middleware to use the credentials provided by the requests, apply the following configuration:
- Middleware OAuth2 Client Credentials
- Kubernetes Secrets
- IngressRoute
- Service & Deployment
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oauth2-client-creds
namespace: apps
spec:
plugin:
# Middleware minimal configuration
oAuthClientCredentials:
# IdP URL to get the access token
url: http://myidp:4444/oauth2/token
# Credentials
clientId: "urn:k8s:secret:oauth-client-nologin:client_id"
clientSecret: "urn:k8s:secret:oauth-client-nologin:client_secret"
apiVersion: v1
kind: Secret
metadata:
name: oauth-client-nologin
namespace: apps
stringData:
client_id: my-oauth-client-ID # Set your ClientID here
client_secret: my-oauth-client-secret # Set your client secret here
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: secure-applications-apigateway-oauth2-client-credentials
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Path(`/oauth2-client-credentials`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: oauth2-client
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
namespace: apps
spec:
replicas: 3
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami
---
apiVersion: v1
kind: Service
metadata:
name: whoami
namespace: apps
spec:
ports:
- port: 80
name: whoami
selector:
app: whoami
Advanced options are described in the reference page.
For example, you can find how to add a cache layer using a Redis store.
Pinning the client authentication method
By default, Hub API Gateway auto-detects whether the authorization server expects client credentials in an HTTP Basic header or in the request body. If the authorization server rejects HTTP Basic, this detection costs one extra request to the authorization server on every token request.
Set clientAuthMethod to skip detection and send credentials the right way on the first
try:
in_header— send credentials using HTTP Basic authentication.in_params— send credentials in the request body.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oauth2-client-creds
namespace: apps
spec:
plugin:
oAuthClientCredentials:
url: http://myidp:4444/oauth2/token
clientId: "urn:k8s:secret:oauth-client-nologin:client_id"
clientSecret: "urn:k8s:secret:oauth-client-nologin:client_secret"
clientAuthMethod: in_params
Auto-detection (the default) tries HTTP Basic first and falls back to the request body if
the authorization server rejects it. Pinning clientAuthMethod removes that fallback along
with the extra request. If you pin the wrong method for your authorization server, every
token request fails instead of falling back. Confirm which style your authorization server
expects before pinning it in production.
Using Custom Scopes
Some authorization servers require specific OAuth scopes to be included in the token request body.
You can configure scopes using the scopes field in the middleware configuration.
Example: Oracle OCI IAM Identity Domains
Oracle OCI IAM Identity Domains requires custom scopes for client credentials authentication. The scopes are sent in the request body to the OAuth2 token endpoint:
- Middleware with Scopes
- Kubernetes Secret
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oauth2-client-creds-oracle
namespace: apps
spec:
plugin:
oAuthClientCredentials:
url: https://idcs-xxxxx.identity.oraclecloud.com/oauth2/v1/token
clientId: "urn:k8s:secret:oracle-client:client_id"
clientSecret: "urn:k8s:secret:oracle-client:client_secret"
scopes:
- urn:opc:resource:consumer::all
apiVersion: v1
kind: Secret
metadata:
name: oracle-client
namespace: apps
stringData:
client_id: your-oracle-client-id
client_secret: your-oracle-client-secret
You can specify multiple scopes as a YAML array. The scopes are sent as a space-separated list in the token request body:
scopes:
- urn:opc:resource:consumer::all
- custom:scope:read
- custom:scope:write
When sent to the authorization server, these will be combined as: urn:opc:resource:consumer::all custom:scope:read custom:scope:write
Related Content
- See the full options in the dedicated section.
- See how to secure your API using OAuth2 Token Introspection.
- See how to secure your API using OAuth2 Client Credentials.
