Secure Access with Distributed Rate Limit and OIDC
When you secure your application using OIDC authentication, you can forward user claims (for example, group memberships) as request headers. By combining this approach with RateLimit or DistributedRateLimit middlewares, you can define rate-limiting policies tailored to specific user attributes.
This guide explains how to chain the OIDC middleware to extract a user claim, forward it to a header, and then apply a rate limit based on that header value. This is useful if you want different rate-limiting rules for different categories of users.
Prerequisites
-
You have an application running behind Traefik Hub API Gateway.
-
You have OIDC authentication configured and working. The OIDC middleware should be forwarding at least one claim to a request header.
Configuring the OIDC middleware
First, let’s configure the OIDC middleware to forward the groups claim to a Groups header. If groups is an array (e.g., ["admin", "support"]
), it will be joined into a comma-separated list.
- OIDC Middleware
- Kubernetes Secrets
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oidc-auth
namespace: apps
spec:
plugin:
oidc:
issuer: "https://my-oidc-provider.com"
redirectUrl: "/callback"
clientID: "urn:k8s:secret:oidc-secrets:clientId"
clientSecret: "urn:k8s:secret:oidc-secrets:clientSecret"
# Extract user group claims and place them into a header named "Groups".
# If "groups" is an array like ["admin", "support"], the header will be:
# Groups: admin,support
forwardHeaders:
Groups: groups
apiVersion: v1
kind: Secret
metadata:
name: oidc-secrets
namespace: apps
stringData:
clientId: "my-oidc-client-id"
clientSecret: "my-oidc-client-secret"
Once this is in place, every authenticated request will include a Groups header with the user’s group claim.
Applying Local RateLimit based on claims
The RateLimit middleware allows you to set local rate limiting rules. By chaining RateLimit after the OIDC middleware, you can apply different limits depending on the user’s group (or any other claim).
For example, to rate-limit based on Groups:
- RateLimit Middleware
- Ingressroute
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: per-group-ratelimit
namespace: apps
spec:
rateLimit:
period: 30s
average: 5
burst: 5
sourceCriterion:
requestHeaderName: Groups
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: secure-app-with-ratelimit
namespace: apps
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`my-app.example.com`)
services:
- name: my-app-service
port: 80
middlewares:
- name: oidc-auth # OIDC middleware sets the Groups header
- name: per-group-ratelimit # RateLimit middleware uses that header
tls:
certResolver: le
In this scenario, each distinct Groups value (e.g., admin,support vs admin) can be rate-limited differently.
Applying RateLimit based on the sub claim (per-user rate limiting)
If you prefer to rate-limit each individual user, you can forward the "sub" claim, which typically identifies a unique user.
For example, to forward sub as User-Sub:
- OIDC Middleware with sub claim
- RateLimit Middleware
- IngressRoute
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oidc-auth-sub
namespace: apps
spec:
plugin:
oidc:
issuer: "https://my-oidc-provider.com"
redirectUrl: "/callback"
clientID: "urn:k8s:secret:oidc-secrets:clientId"
clientSecret: "urn:k8s:secret:oidc-secrets:clientSecret"
forwardHeaders:
User-Sub: sub
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: per-user-ratelimit
namespace: apps
spec:
rateLimit:
period: 30s
average: 10
burst: 10
sourceCriterion:
requestHeaderName: User-Sub
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: secure-app-with-ratelimit
namespace: apps
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`my-app.example.com`)
services:
- name: my-app-service
port: 80
middlewares:
- name: oidc-auth # OIDC middleware sets the User-Sub header
- name: per-user-ratelimit # RateLimit middleware uses that header
tls:
certResolver: le
Applying Distributed RateLimit Based on Claims
If you want your rate limiting to apply across the entire cluster rather than per instance, you can use the DistributedRateLimit middleware. It uses a persistent store (like Redis) and enforces limits consistently, no matter which gateway instance handles the request.
You can apply DistributedRateLimit using either Groups, User-Sub, or another claim.
For example, if your OIDC provider includes a cid (client/application ID) claim, you can forward it as App-ID
:
- OIDC Middleware with cid claim
- Distributed RateLimit Middleware
- IngressRoute
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oidc-auth-cid
namespace: apps
spec:
plugin:
oidc:
issuer: "https://my-oidc-provider.com"
redirectUrl: "/callback"
clientID: "urn:k8s:secret:oidc-secrets:clientId"
clientSecret: "urn:k8s:secret:oidc-secrets:clientSecret"
forwardHeaders:
App-ID: cid
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: distributed-ratelimit
namespace: apps
spec:
plugin:
distributedRateLimit:
limit: 5
period: 30s
burst: 5
sourceCriterion:
requestHeaderName: App-ID
store:
redis:
endpoints:
- redis-master.apps.svc.cluster.local:6379
password: "urn:k8s:secret:redis:password"
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: secure-app-with-distributedrl
namespace: apps
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`my-app.example.com`)
services:
- name: my-app-service
port: 80
middlewares:
- name: oidc-auth # OIDC sets app-id header
- name: distributed-ratelimit # DistributedRateLimit uses the header
tls:
certResolver: le
This DistributedRateLimit middleware applies the same logic as the local one, but ensures that requests are limited cluster-wide. The chosen header (App-ID
in this example) determines the bucket key.
Requests sharing the same App-ID value are subject to the same global rate limit, ensuring consistent enforcement across your entire cluster.
Related Content
- Refer to OIDC Middleware documentation for details on how to set up OIDC and extract user claims in its dedicated section.
- For full RateLimit options, see the RateLimit reference in its dedicated section.
- For full DistributedRateLimit options, see the DistributedRateLimit reference its dedicated section.
- Check out Redis configuration for how to configure persistent storage for DistributedRateLimit in its dedicated section