This is a practical setup guide to protect an app behind Traefik Gateway API using oauth2-proxy with
Microsoft (Entra ID / Azure AD) login.
1) Target Architecture
• gateway-api namespace: Traefik Gateway
• oauth2-proxy namespace: oauth2-proxy deployment/service
• your-app namespace: your app service + auth middleware + app route
• Same hostname for app + oauth callbacks, for example:
• https://app.example.com/
• https://app.example.com/oauth2/*
Flow:
- User hits /
- Traefik checks auth via oauth2-proxy (/oauth2/auth)
- If unauthenticated, user is sent to Microsoft login
- Microsoft redirects to /oauth2/callback
- oauth2-proxy sets cookie, then user can access app ────────────────────────────────────────
2) Prerequisites
• Kubernetes cluster with Gateway API CRDs installed
• Traefik installed with:
• Kubernetes Gateway provider enabled
• Kubernetes CRD provider enabled (for Traefik Middleware CRDs)
• A TLS cert configured on Gateway listener
• A DNS record for your app hostname -> Traefik LB
────────────────────────────────────────
3) Microsoft Entra ID App Registration
In Azure Portal:
- Create/register an application
- Add redirect URI:
• https:///oauth2/callback - Create client secret
- Note:
• TENANT_ID
• CLIENT_ID
• CLIENT_SECRET - API permissions:
• At minimum, make sure scopes used by oauth2-proxy are allowed
• If you use Graph scopes, grant admin consent as needed
4) Deploy oauth2-proxy
4.1 Namespace + secret
kubectl create namespace oauth2-proxy
kubectl -n oauth2-proxy create secret generic oauth2-proxy \
--from-literal=client-id='<CLIENT_ID>' \
--from-literal=client-secret='<CLIENT_SECRET>' \
--from-literal=cookie-secret='<BASE64_32_BYTE_SECRET>Generate cookie secret example:
python3 - <<'PY'
import os,base64
print(base64.urlsafe_b64encode(os.urandom(32)).decode())
PY4.2 oauth2-proxy manifest (example)
apiVersion: v1
kind: ConfigMap
metadata:
name: oauth2-proxy
namespace: oauth2-proxy
data:
oauth2_proxy.cfg: |
email_domains = [ "*" ]
upstreams = [ "file:///dev/null" ]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: oauth2-proxy
namespace: oauth2-proxy
spec:
replicas: 1
selector:
matchLabels:
app: oauth2-proxy
template:
metadata:
labels:
app: oauth2-proxy
spec:
containers:
- name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:v7.12.0
args:
- --http-address=0.0.0.0:4180
- --provider=azure
- --azure-tenant=<TENANT_ID>
- --oidc-issuer-url=https://login.microsoftonline.com/<TENANT_ID>/v2.0
- --redirect-url=https://<APP_HOST>/oauth2/callback
- --scope=openid profile email
- --cookie-name=_oauth2_proxy
- --cookie-secure=true
- --cookie-samesite=lax
- --reverse-proxy=true
- --skip-provider-button=true
- --config=/etc/oauth2_proxy/oauth2_proxy.cfg
env:
- name: OAUTH2_PROXY_CLIENT_ID
valueFrom:
secretKeyRef:
name: oauth2-proxy
key: client-id
- name: OAUTH2_PROXY_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: oauth2-proxy
key: client-secret
- name: OAUTH2_PROXY_COOKIE_SECRET
valueFrom:
secretKeyRef:
name: oauth2-proxy
key: cookie-secret
ports:
- containerPort: 4180
name: http
volumeMounts:
- name: config
mountPath: /etc/oauth2_proxy/oauth2_proxy.cfg
subPath: oauth2_proxy.cfg
volumes:
- name: config
configMap:
name: oauth2-proxy
---
apiVersion: v1
kind: Service
metadata:
name: oauth2-proxy
namespace: oauth2-proxy
spec:
selector:
app: oauth2-proxy
ports:
- name: http
port: 80
targetPort: 41805) Route /oauth2 to oauth2-proxy (Gateway API)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: oauth2-proxy-route
namespace: oauth2-proxy
spec:
hostnames:
- <APP_HOST>
parentRefs:
- name: traefik-gateway
namespace: gateway-api
sectionName: https
rules:
- matches:
- path:
type: PathPrefix
value: /oauth2
backendRefs:
- name: oauth2-proxy
port: 806) Protect app route with Traefik Middleware (ForwardAuth)
Important: Middleware must exist in the same namespace as the app route.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oauth2-proxy-auth
namespace: <APP_NS>
spec:
forwardAuth:
address: http://oauth2-proxy.oauth2-proxy.svc.cluster.local/oauth2/auth
trustForwardHeader: true
authResponseHeaders:
- X-Auth-Request-User
- X-Auth-Request-Email
- X-Auth-Request-Access-Token
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: <APP_NS>
spec:
hostnames:
- <APP_HOST>
parentRefs:
- name: traefik-gateway
namespace: gateway-api
sectionName: https
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: ExtensionRef
extensionRef:
group: traefik.io
kind: Middleware
name: oauth2-proxy-auth
backendRefs:
- name: <APP_SERVICE_NAME>
port: 80