mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-12 04:04:26 +00:00
Header templates can now emit an object or array claim as one JSON
header. Example: {{get .Claims "tenant" | toJson}}. The backend parses
the claim, so the middleware does not need to know its schema.
The helper adds no new access path. The validator treats toJson like
default and checks its arguments. A claim must be on the whitelist, and
a dump of the whole claims map is rejected. An absent or empty claim
skips the header. The JSON encoder escapes control characters.
A rendered header value over 8192 bytes is still dropped. The drop is
now logged at error level, with the header name and without the value.
Other sanitizer drops stay at debug level.
Tests cover value types, edge cases, whitelist bypass attempts, token
leaks and header injection. A new yaegi check runs the helper under the
interpreter. README, configuration docs and the plugin manifest show the
new helper.
122 lines
5.1 KiB
YAML
122 lines
5.1 KiB
YAML
displayName: Traefik OIDC
|
|
type: middleware
|
|
|
|
import: github.com/lukaszraczylo/traefikoidc
|
|
|
|
summary: |
|
|
OpenID Connect authentication middleware for Traefik. Replaces forward-auth
|
|
+ oauth2-proxy with a single plugin that auto-detects all major OIDC
|
|
providers (Google, Azure AD, Auth0, Okta, Keycloak, AWS Cognito, GitLab,
|
|
generic) and OAuth 2.0 for GitHub.
|
|
|
|
Features: ID-token validation with auto-discovery, session encryption,
|
|
proactive token refresh, RBAC via roles/groups claims, domain restriction,
|
|
templated downstream headers, security headers (CSP, HSTS, CORS), rate
|
|
limiting, PKCE, opaque-token introspection (RFC 7662), back/front-channel
|
|
logout, Dynamic Client Registration (RFC 7591), and Redis-backed shared
|
|
state for multi-replica deployments.
|
|
|
|
Full documentation: https://github.com/lukaszraczylo/traefikoidc
|
|
|
|
testData:
|
|
# Required
|
|
providerURL: https://accounts.google.com
|
|
clientID: 1234567890.apps.googleusercontent.com
|
|
clientSecret: your-client-secret
|
|
# Alternative: RFC 7523 private_key_jwt client authentication (Entra ID,
|
|
# Okta, Auth0, Keycloak). Replaces clientSecret with a signed JWT assertion.
|
|
# See README "Client authentication via private key JWT".
|
|
# clientAuthMethod: private_key_jwt
|
|
# clientAssertionKeyID: my-key-2026
|
|
# clientAssertionAlg: RS256 # default; or PS256/384/512, ES256/384/512
|
|
# # File path option:
|
|
# clientAssertionKeyPath: /etc/traefik/oidc/client-key.pem
|
|
# # Or inline PEM (PKCS#8 / PKCS#1 / SEC1):
|
|
# clientAssertionPrivateKey: |
|
|
# -----BEGIN PRIVATE KEY-----
|
|
# MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDexampleexample
|
|
# -----END PRIVATE KEY-----
|
|
sessionEncryptionKey: potato-secret-is-at-least-32-bytes-long
|
|
callbackURL: /oauth2/callback
|
|
|
|
# Common production knobs
|
|
logoutURL: /oauth2/logout
|
|
postLogoutRedirectURI: /
|
|
forceHTTPS: true # default; only set false for plaintext HTTP local dev
|
|
logLevel: info
|
|
rateLimit: 100
|
|
|
|
# Access control
|
|
allowedUserDomains:
|
|
- company.com
|
|
allowedRolesAndGroups:
|
|
- admin
|
|
- developer
|
|
excludedURLs:
|
|
- /health
|
|
- /metrics
|
|
|
|
# Scopes are appended to the defaults ["openid", "profile", "email"]
|
|
scopes:
|
|
- roles
|
|
|
|
# Templated headers forwarded to backends. Values are Go templates and must
|
|
# be written with plain double braces — the catalog analyzer feeds them to
|
|
# the plugin verbatim (issue #151; quadruple braces do NOT get collapsed).
|
|
# Only when your dynamic config file is rendered by Traefik's file-provider
|
|
# Go templating do the braces need escaping there, e.g.
|
|
# value: "{{`{{.Claims.email}}`}}"
|
|
# (see README "Templated headers").
|
|
headers:
|
|
- name: X-User-Email
|
|
value: "{{.Claims.email}}"
|
|
- name: Authorization
|
|
value: "Bearer {{.AccessToken}}"
|
|
# Object/array claim as one JSON header; the claim must be whitelisted.
|
|
- name: X-Tenant
|
|
value: '{{get .Claims "tenant" | toJson}}'
|
|
|
|
# Extends the built-in claim whitelist for templated headers.
|
|
allowedClaims:
|
|
- tenant
|
|
|
|
# Security headers (default profile is enabled out of the box)
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: default
|
|
|
|
# Optional: Redis for multi-replica deployments. See docs/REDIS.md.
|
|
# redis:
|
|
# enabled: true
|
|
# address: redis:6379
|
|
# password: urn:k8s:secret:redis:password
|
|
# cacheMode: hybrid
|
|
|
|
# Optional: bearer-token authentication for M2M (machine-to-machine) API
|
|
# clients. Default off. When enabled, requests presenting
|
|
# "Authorization: Bearer <jwt>" are validated against the configured OIDC
|
|
# provider (signature/issuer/audience/exp) and forwarded without creating
|
|
# a cookie session. The bearer path REJECTS ID tokens, requires a non-
|
|
# default audience, and never trusts the `email` claim as the identifier.
|
|
# See docs/BEARER_AUTH.md for the full threat model.
|
|
#
|
|
# enableBearerAuth: true # opt-in
|
|
# audience: https://api.example.com # REQUIRED when bearer is enabled
|
|
# bearerIdentifierClaim: sub # default; used as X-Forwarded-User. `email` is rejected.
|
|
# stripAuthorizationHeader: true # default; drops the raw token before forwarding
|
|
# bearerEmitWWWAuthenticate: true # default; RFC 6750 hint on 401s
|
|
# bearerOverridesCookie: false # default; cookie wins when both are present
|
|
# requireTokenIntrospection: false # opt-in; calls RFC 7662 introspection per request
|
|
# introspectionURL: https://idp.example.com/oauth/introspect # manual override; set when discovery omits introspection_endpoint
|
|
# maxTokenAgeSeconds: 86400 # 24h cap on iat (rejects clock-skew/forever tokens)
|
|
# maxIdentifierLength: 256 # cap on the sanitised principal identifier
|
|
# bearerFailureThreshold: 20 # consecutive 401s/IP that trip the throttle
|
|
# bearerFailureWindowSeconds: 60 # rolling window over which 401s are counted
|
|
# bearerFailurePenaltySeconds: 60 # 429 + Retry-After duration after threshold trips
|
|
|
|
# Optional: RFC 8707 resource indicator, alternative to `audience` for
|
|
# supporting IdPs. See docs/RFC8707.md for exact request behavior and
|
|
# provider support.
|
|
# resource: https://api.example.com
|
|
|