mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-06-05 22:44:17 +00:00
e64fc7f730
* Add redis support for distributed caching * Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * ... and another all nighter. * fixup! ... and another all nighter. * fixup! fixup! ... and another all nighter. * fixup! fixup! fixup! ... and another all nighter. * Resolve issue #85 by adding ability to set custom claims in JWT tokens * Remove redundant validation in auth middleware ( issue #89 ) * Add ability to set cookie prefix for session cookies ( #87 ) * fixup! Add ability to set cookie prefix for session cookies ( #87 ) * Add ability to set cookie max age - issue #91 * Potential fix for code scanning alert no. 10: Size computation for allocation may overflow Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fixup! Merge main into 0.8.0-redis: resolve conflicts --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
1515 lines
58 KiB
YAML
1515 lines
58 KiB
YAML
displayName: Traefik OIDC
|
|
type: middleware
|
|
|
|
import: github.com/lukaszraczylo/traefikoidc
|
|
|
|
summary: |
|
|
Universal OpenID Connect (OIDC) authentication middleware for Traefik.
|
|
|
|
This middleware replaces the need for forward-auth and oauth2-proxy when using Traefik as a reverse proxy.
|
|
It provides a complete OIDC authentication solution with features including domain restrictions,
|
|
role-based access control, session management, comprehensive security headers, automatic token refresh,
|
|
and support for all major OIDC providers with automatic configuration.
|
|
|
|
🎯 SUPPORTED PROVIDERS (Auto-Detection):
|
|
✅ Google - Full OIDC, auto-configured for Workspace
|
|
✅ Azure AD - Enterprise OIDC with tenant/group support
|
|
✅ Auth0 - Flexible OIDC with custom claims
|
|
✅ Okta - Enterprise SSO with MFA support
|
|
✅ Keycloak - Self-hosted OIDC with full customization
|
|
✅ AWS Cognito - Managed OIDC with regional endpoints
|
|
✅ GitLab - Both GitLab.com and self-hosted instances
|
|
⚠️ GitHub - OAuth 2.0 only (limited: API access, no user claims)
|
|
✅ Generic OIDC - Any RFC-compliant OIDC provider
|
|
|
|
🔧 KEY FEATURES:
|
|
- Automatic provider detection and configuration
|
|
- Comprehensive security headers (CSP, HSTS, CORS, custom profiles)
|
|
- Domain restrictions and role-based access control
|
|
- Automatic token refresh and session management
|
|
- Rate limiting and brute force protection
|
|
- Flexible configuration with multiple deployment scenarios
|
|
- Memory-efficient operation with automatic cleanup
|
|
- Extensive logging and debugging capabilities
|
|
- Redis cache support for multi-replica deployments with automatic failover
|
|
It supports various authentication scenarios including:
|
|
|
|
- Basic authentication with customizable callback and logout URLs
|
|
- Email domain restrictions to limit access to specific organizations
|
|
- Role and group-based access control based on OIDC claims
|
|
- Public URLs that bypass authentication (excluded paths)
|
|
- Secure session management with encrypted cookies
|
|
- Automatic token validation and refresh
|
|
- Comprehensive security headers with multiple security profiles
|
|
- Rate limiting to prevent brute force attacks
|
|
- Custom headers using templated values from OIDC claims
|
|
- Flexible CORS configuration for API endpoints
|
|
- Configurable logging levels for debugging and monitoring
|
|
|
|
testData:
|
|
# Required parameters
|
|
providerURL: https://accounts.google.com # Base URL of the OIDC provider
|
|
clientID: 1234567890.apps.googleusercontent.com # OAuth 2.0 client identifier
|
|
clientSecret: secret # OAuth 2.0 client secret
|
|
callbackURL: /oauth2/callback # Path where the OIDC provider will redirect after authentication
|
|
sessionEncryptionKey: potato-secret-is-at-least-32-bytes-long # Key used to encrypt session data (must be at least 32 bytes)
|
|
|
|
# Optional parameters with defaults
|
|
logoutURL: /oauth2/logout # Path for handling logout requests (if not provided, it will be set to callbackURL + "/logout")
|
|
postLogoutRedirectURI: /oidc/different-logout # URL to redirect to after logout (default: "/")
|
|
|
|
scopes: # Additional scopes to append to defaults ["openid", "profile", "email"]
|
|
- roles # Result: ["openid", "profile", "email", "roles"]
|
|
|
|
allowedUserDomains: # Restricts access to specific email domains (if not provided, relies on OIDC provider)
|
|
- company.com
|
|
- subsidiary.com
|
|
|
|
allowedUsers: # Restricts access to specific email addresses regardless of domain
|
|
- specific-user@company.com
|
|
- another-user@gmail.com
|
|
|
|
allowedRolesAndGroups: # Restricts access to users with specific roles or groups (if not provided, no role/group restrictions)
|
|
- guest-endpoints
|
|
- admin
|
|
- developer
|
|
|
|
# Custom claim names for Auth0 and other providers with namespaced claims
|
|
roleClaimName: roles # JWT claim name for extracting user roles (default: "roles")
|
|
groupClaimName: groups # JWT claim name for extracting user groups (default: "groups")
|
|
|
|
# ⚠️ CRITICAL for TLS termination scenarios (AWS ALB, Cloud Load Balancers, etc.)
|
|
# When NOT specified in config: defaults to FALSE (Go zero value)
|
|
# When running behind load balancer that terminates TLS: MUST set to TRUE
|
|
# See: https://github.com/lukaszraczylo/traefikoidc/issues/82
|
|
forceHTTPS: true # Forces HTTPS scheme for redirect URIs (default when not specified: false)
|
|
logLevel: debug # Sets logging verbosity: debug, info, error (default: info)
|
|
rateLimit: 100 # Maximum number of requests per second (default: 100, minimum: 10)
|
|
|
|
excludedURLs: # Lists paths that bypass authentication
|
|
- /login # covers /login, /login/me, /login/reminder etc.
|
|
- /public
|
|
- /health
|
|
- /metrics
|
|
|
|
headers: # Custom headers to set with templated values from claims and tokens
|
|
# NOTE: Use double curly braces to escape template expressions in YAML
|
|
# See the headers section in configuration below for details
|
|
- name: "X-User-Email"
|
|
value: "{{{{.Claims.email}}}}"
|
|
- name: "X-User-ID"
|
|
value: "{{{{.Claims.sub}}}}"
|
|
- name: "Authorization"
|
|
value: "Bearer {{{{.AccessToken}}}}"
|
|
- name: "X-User-Roles"
|
|
value: "{{{{range $i, $e := .Claims.roles}}}}{{{{if $i}}}},{{{{end}}}}{{{{$e}}}}{{{{end}}}}"
|
|
|
|
# Advanced parameters (usually discovered automatically from provider metadata)
|
|
revocationURL: https://accounts.google.com/revoke # Endpoint for revoking tokens
|
|
oidcEndSessionURL: https://accounts.google.com/logout # Provider's end session endpoint
|
|
enablePKCE: false # Enables PKCE (Proof Key for Code Exchange) for additional security
|
|
cookieDomain: "" # Explicit domain for session cookies (e.g., ".example.com" for multi-subdomain setups)
|
|
cookiePrefix: "" # Custom prefix for cookie names (e.g., "_oidc_myapp_" for session isolation between middleware instances)
|
|
sessionMaxAge: 86400 # Maximum session age in seconds (default: 86400 = 24 hours, 0 = use default)
|
|
overrideScopes: false # When true, replaces default scopes instead of appending (default: false)
|
|
refreshGracePeriodSeconds: 60 # Seconds before token expiry to attempt proactive refresh (default: 60)
|
|
|
|
# Auth0 / Custom API Audience Configuration
|
|
audience: "" # Custom audience for access token validation (default: clientID)
|
|
strictAudienceValidation: false # Reject sessions with audience mismatch (prevents token confusion attacks)
|
|
allowOpaqueTokens: false # Enable opaque (non-JWT) access token support via RFC 7662 introspection
|
|
requireTokenIntrospection: false # Force introspection for opaque tokens (requires introspection endpoint)
|
|
disableReplayDetection: false # Disable JTI replay detection for multi-replica deployments (default: false)
|
|
|
|
# Security Headers Configuration (enabled by default with 'default' profile)
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: "default" # Options: default, strict, development, api, custom
|
|
|
|
# CORS configuration for API endpoints
|
|
corsEnabled: false
|
|
corsAllowedOrigins:
|
|
- "https://your-frontend.com"
|
|
- "https://*.example.com"
|
|
corsAllowCredentials: true
|
|
|
|
# Cross-origin policies
|
|
permissionsPolicy: "geolocation=(), camera=(), microphone=()"
|
|
crossOriginEmbedderPolicy: "require-corp"
|
|
crossOriginOpenerPolicy: "same-origin"
|
|
crossOriginResourcePolicy: "same-origin"
|
|
|
|
# Custom headers
|
|
customHeaders:
|
|
X-Custom-Header: "production"
|
|
X-API-Version: "v1"
|
|
|
|
# Example with Redis cache for multi-replica deployments
|
|
testDataWithRedis:
|
|
# Required OIDC parameters (same as standard configuration)
|
|
providerURL: https://auth.example.com
|
|
clientID: your-client-id
|
|
clientSecret: your-client-secret
|
|
callbackURL: /oauth2/callback
|
|
sessionEncryptionKey: your-64-character-encryption-key-at-least-32-bytes
|
|
|
|
# Standard optional parameters
|
|
logLevel: info
|
|
allowedUserDomains:
|
|
- company.com
|
|
|
|
# Redis cache configuration for multi-replica support
|
|
redis:
|
|
enabled: true # Enable Redis caching
|
|
address: "redis:6379" # Redis server address
|
|
password: "redis-password" # Redis authentication password
|
|
db: 0 # Redis database number (0-15)
|
|
keyPrefix: "traefikoidc:" # Prefix for all Redis keys
|
|
cacheMode: "hybrid" # Cache mode: redis, hybrid, or memory
|
|
poolSize: 20 # Maximum number of connections
|
|
connectTimeout: 5 # Connection timeout in seconds
|
|
readTimeout: 3 # Read operation timeout
|
|
writeTimeout: 3 # Write operation timeout
|
|
enableTLS: false # Use TLS for Redis connection
|
|
tlsSkipVerify: false # Skip TLS certificate verification
|
|
hybridL1Size: 500 # L1 cache size for hybrid mode
|
|
hybridL1MemoryMB: 10 # L1 memory limit for hybrid mode
|
|
enableCircuitBreaker: true # Enable circuit breaker
|
|
circuitBreakerThreshold: 5 # Failures before opening circuit
|
|
circuitBreakerTimeout: 60 # Timeout before retry (seconds)
|
|
enableHealthCheck: true # Enable periodic health checks
|
|
healthCheckInterval: 30 # Health check interval (seconds)
|
|
|
|
# --- Common Configuration Examples ---
|
|
#
|
|
# 🔒 HIGH-SECURITY CONFIGURATION
|
|
# testDataHighSecurity:
|
|
# providerURL: https://login.microsoftonline.com/your-tenant-id/v2.0
|
|
# clientID: your-azure-client-id
|
|
# clientSecret: your-azure-client-secret
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "maximum-security-key-at-least-32-bytes-long"
|
|
# rateLimit: 50 # Restrictive rate limiting
|
|
# allowedUserDomains: ["company.com"] # Domain restriction
|
|
# allowedRolesAndGroups: ["admin", "security-team"] # Role restriction
|
|
# securityHeaders:
|
|
# enabled: true
|
|
# profile: "strict" # Maximum security headers
|
|
# corsEnabled: false # No CORS in high-security mode
|
|
# logLevel: info
|
|
|
|
# 🧑💻 DEVELOPMENT CONFIGURATION
|
|
# testDataDevelopment:
|
|
# providerURL: https://your-dev-provider.com
|
|
# clientID: dev-client-id
|
|
# clientSecret: dev-client-secret
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "development-key-at-least-32-bytes-long"
|
|
# forceHTTPS: false # Allow HTTP in development
|
|
# excludedURLs: ["/health", "/metrics", "/debug"]
|
|
# securityHeaders:
|
|
# enabled: true
|
|
# profile: "development" # Relaxed security for development
|
|
# corsEnabled: true
|
|
# corsAllowedOrigins: ["http://localhost:*", "http://127.0.0.1:*"]
|
|
# logLevel: debug
|
|
|
|
# 🌐 API CONFIGURATION
|
|
# testDataAPI:
|
|
# providerURL: https://your-auth0-domain.auth0.com
|
|
# clientID: api-client-id
|
|
# clientSecret: api-client-secret
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "api-gateway-key-at-least-32-bytes-long"
|
|
# refreshGracePeriodSeconds: 120
|
|
# securityHeaders:
|
|
# enabled: true
|
|
# profile: "api"
|
|
# corsEnabled: true
|
|
# corsAllowedOrigins: ["https://app.example.com"]
|
|
# corsAllowedMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
|
|
# corsAllowedHeaders: ["Authorization", "Content-Type", "X-API-Key"]
|
|
# headers: # Custom headers with OIDC claims (use double curly braces)
|
|
# - name: "X-User-Email"
|
|
# value: "{{{{.Claims.email}}}}"
|
|
# - name: "X-User-ID"
|
|
# value: "{{{{.Claims.sub}}}}"
|
|
|
|
# --- Provider Specific Configuration Examples ---
|
|
#
|
|
# This middleware supports 9+ OIDC providers with automatic detection:
|
|
# ✅ Google - Full OIDC with auto-configuration
|
|
# ✅ Azure AD - Enterprise OIDC with tenant support
|
|
# ✅ Auth0 - Flexible OIDC with custom claims
|
|
# ✅ Okta - Enterprise OIDC with MFA support
|
|
# ✅ Keycloak - Self-hosted OIDC with full customization
|
|
# ✅ AWS Cognito - Managed OIDC with regional endpoints
|
|
# ✅ GitLab - Both GitLab.com and self-hosted
|
|
# ⚠️ GitHub - OAuth 2.0 only (not OIDC, limited functionality)
|
|
# ✅ Generic OIDC - Any RFC-compliant OIDC provider
|
|
#
|
|
# Uncomment and adapt the relevant section for your provider.
|
|
# Remember to replace placeholder values with your actual credentials.
|
|
# For all providers, ensure claims like email, roles, and groups are
|
|
# configured to be included in the ID TOKEN (this plugin validates ID tokens).
|
|
|
|
# --- Keycloak Example ---
|
|
# testDataKeycloak:
|
|
# providerURL: https://your-keycloak-domain/realms/your-realm # e.g., http://localhost:8080/realms/master
|
|
# clientID: your-keycloak-client-id
|
|
# clientSecret: your-keycloak-client-secret # Store securely, e.g., urn:k8s:secret:namespace:secret-name:key
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-keycloak"
|
|
# scopes: # Default ["openid", "profile", "email"] are usually sufficient. Add others if mappers depend on them.
|
|
# - roles # Example: if you mapped Keycloak roles to a 'roles' claim in the ID token
|
|
# - groups # Example: if you mapped Keycloak groups to a 'groups' claim in the ID token
|
|
# allowedRolesAndGroups: # Corresponds to 'Token Claim Name' in Keycloak mappers
|
|
# - admin
|
|
# - editor
|
|
# # Ensure Keycloak client mappers add 'email', 'roles', 'groups' etc. to the ID Token.
|
|
# # See README.md "Provider Configuration Recommendations" for Keycloak.
|
|
|
|
# --- Azure AD (Microsoft Entra ID) Example ---
|
|
# testDataAzureAD:
|
|
# providerURL: https://login.microsoftonline.com/your-tenant-id/v2.0 # Replace your-tenant-id
|
|
# clientID: your-azure-ad-client-id
|
|
# clientSecret: your-azure-ad-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-azure"
|
|
# scopes: # Defaults ["openid", "profile", "email"] are good.
|
|
# # Azure AD may require specific scopes for certain graph API permissions if you were to use the access token,
|
|
# # but for ID token claims, defaults are often enough.
|
|
# # Group claims need to be configured in Azure AD App Registration -> Token Configuration -> Add groups claim.
|
|
# allowedUserDomains:
|
|
# - yourcompany.com
|
|
# allowedRolesAndGroups: # If you configured group claims (typically 'groups') or app roles in Azure AD
|
|
# - "group-object-id-1" # Azure AD group claims can be Object IDs by default
|
|
# - "AppRoleName"
|
|
# # See README.md "Provider Configuration Recommendations" for Azure AD.
|
|
|
|
# --- Google Workspace / Google Cloud Identity Example ---
|
|
# testDataGoogle:
|
|
# providerURL: https://accounts.google.com # Standard Google OIDC endpoint
|
|
# clientID: your-google-client-id.apps.googleusercontent.com
|
|
# clientSecret: your-google-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-google"
|
|
# scopes: # Auto-detects Google and applies proper configuration
|
|
# # Do NOT add 'offline_access' - plugin automatically handles Google-specific parameters
|
|
# allowedUserDomains: # Useful for Google Workspace domain restriction
|
|
# - your-gsuite-domain.com
|
|
# refreshGracePeriodSeconds: 300 # Optional: Refresh 5 min before expiry
|
|
# # Google auto-config: Uses access_type=offline, prompt=consent, filters unsupported scopes
|
|
# # Available claims: email, sub, name, given_name, family_name, picture, hd (hosted domain)
|
|
|
|
# --- Okta Example ---
|
|
# testDataOkta:
|
|
# providerURL: https://your-tenant.okta.com/oauth2/default # Use your Okta domain and auth server
|
|
# clientID: your-okta-client-id
|
|
# clientSecret: your-okta-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-okta"
|
|
# scopes:
|
|
# - groups # Include for group-based access control
|
|
# allowedRolesAndGroups:
|
|
# - admin
|
|
# - developer
|
|
# - "Everyone" # Default Okta group
|
|
# # Okta config: Create OIDC Web App in admin console, configure Groups claim
|
|
# # Available claims: email, sub, name, groups, custom attributes
|
|
|
|
# --- AWS Cognito Example ---
|
|
# testDataCognito:
|
|
# providerURL: https://cognito-idp.us-east-1.amazonaws.com/us-east-1_YourUserPool # Regional endpoint
|
|
# clientID: your-cognito-client-id
|
|
# clientSecret: your-cognito-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-cognito"
|
|
# scopes:
|
|
# - aws.cognito.signin.user.admin # Cognito-specific scope
|
|
# allowedRolesAndGroups:
|
|
# - admin
|
|
# - user
|
|
# # Cognito config: Create User Pool, App Client with authorization code grant
|
|
# # Available claims: email, sub, cognito:username, cognito:groups, custom attributes
|
|
|
|
# --- GitLab Example ---
|
|
# testDataGitLab:
|
|
# providerURL: https://gitlab.com # For GitLab.com, or use your self-hosted URL
|
|
# clientID: your-gitlab-client-id
|
|
# clientSecret: your-gitlab-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-gitlab"
|
|
# scopes:
|
|
# - read_user
|
|
# - read_api # For GitLab API access
|
|
# allowedUserDomains:
|
|
# - yourcompany.com # Optional domain restriction
|
|
# # GitLab config: Create application in GitLab Admin Area > Applications
|
|
# # Available claims: email, sub, name, nickname, preferred_username
|
|
|
|
# --- GitHub OAuth 2.0 Example (⚠️ Limited Functionality) ---
|
|
# testDataGitHub:
|
|
# providerURL: https://github.com/login/oauth # GitHub OAuth endpoint (NOT OIDC)
|
|
# clientID: your-github-client-id
|
|
# clientSecret: your-github-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-github"
|
|
# scopes:
|
|
# - user:email
|
|
# - read:user
|
|
# # ⚠️ IMPORTANT: GitHub uses OAuth 2.0, NOT OpenID Connect
|
|
# # - No ID tokens available (access tokens only)
|
|
# # - No refresh tokens (users must re-authenticate when tokens expire)
|
|
# # - No standard OIDC claims
|
|
# # - Use only for GitHub API access, not for user authentication with claims
|
|
# # GitHub config: Create OAuth App in GitHub Settings > Developer settings
|
|
|
|
# --- Auth0 Example ---
|
|
# testDataAuth0:
|
|
# providerURL: https://your-auth0-domain.auth0.com # Replace with your Auth0 domain
|
|
# clientID: your-auth0-client-id
|
|
# clientSecret: your-auth0-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-auth0"
|
|
#
|
|
# # Auth0 Audience Configuration (for custom APIs)
|
|
# # Scenario 1 (Recommended): Custom API with JWT access tokens
|
|
# audience: "https://my-api.example.com" # Your API identifier from Auth0 dashboard
|
|
# strictAudienceValidation: true # Enforce proper audience validation for security
|
|
#
|
|
# # Scenario 2 (Backward Compatible): Default audience (uses client_id)
|
|
# # audience: "" # Leave empty or omit to use client_id as audience
|
|
# # strictAudienceValidation: false # Allows fallback to ID token validation (logs warnings)
|
|
#
|
|
# # Scenario 3: Opaque (non-JWT) access tokens
|
|
# # allowOpaqueTokens: true # Enable opaque token support
|
|
# # requireTokenIntrospection: true # Require RFC 7662 token introspection
|
|
#
|
|
# scopes: # Defaults ["openid", "profile", "email"]. Add custom scopes if your Auth0 Rules/Actions require them.
|
|
# - read:custom_data # Example custom scope
|
|
# allowedRolesAndGroups: # Based on claims added via Auth0 Rules or Actions (e.g. namespaced claims)
|
|
# - "https://your-app.com/roles:admin"
|
|
# - editor
|
|
# # Use Auth0 Rules or Actions to add custom claims (roles, permissions) to the ID Token.
|
|
# # Ensure postLogoutRedirectURI is in Auth0 app's "Allowed Logout URLs".
|
|
# # For detailed Auth0 audience configuration, see AUTH0_AUDIENCE_GUIDE.md
|
|
|
|
# --- Generic OIDC Provider Example ---
|
|
# testDataGenericOIDC:
|
|
# providerURL: https://your-generic-oidc-provider.com/oidc # Issuer URL for your provider
|
|
# clientID: your-generic-client-id
|
|
# clientSecret: your-generic-client-secret # Store securely
|
|
# callbackURL: /oauth2/callback
|
|
# sessionEncryptionKey: "a-very-secure-key-at-least-32-bytes-long-for-generic"
|
|
# scopes: # Must include "openid". "profile" and "email" are common.
|
|
# - openid
|
|
# - profile
|
|
# - email
|
|
# - custom_scope_for_claims # If your provider needs specific scopes for ID token claims
|
|
# allowedRolesAndGroups:
|
|
# - user_role_from_id_token
|
|
# # Consult your provider's documentation on how to map attributes/roles/groups to ID Token claims.
|
|
# # Verify ID Token contents (e.g. jwt.io) to see available claims.
|
|
# # See README.md "Provider Configuration Recommendations" for Generic OIDC.
|
|
|
|
# Configuration documentation
|
|
configuration:
|
|
providerURL:
|
|
type: string
|
|
description: |
|
|
The base URL of the OIDC provider. This is the issuer URL that will be used to discover
|
|
OIDC endpoints like authorization, token, and JWKS URIs.
|
|
|
|
Supported providers (auto-detected from URL):
|
|
- https://accounts.google.com (Google)
|
|
- https://login.microsoftonline.com/tenant-id/v2.0 (Azure AD)
|
|
- https://your-auth0-domain.auth0.com (Auth0)
|
|
- https://your-tenant.okta.com/oauth2/default (Okta)
|
|
- https://your-keycloak/auth/realms/your-realm (Keycloak)
|
|
- https://cognito-idp.region.amazonaws.com/pool-id (AWS Cognito)
|
|
- https://gitlab.com (GitLab)
|
|
- https://github.com/login/oauth (GitHub - OAuth 2.0 only)
|
|
- Any RFC-compliant OIDC provider (Generic)
|
|
required: true
|
|
|
|
clientID:
|
|
type: string
|
|
description: |
|
|
The OAuth 2.0 client identifier obtained from your OIDC provider.
|
|
This is the public identifier for your application.
|
|
required: true
|
|
|
|
clientSecret:
|
|
type: string
|
|
description: |
|
|
The OAuth 2.0 client secret obtained from your OIDC provider.
|
|
This should be kept confidential and not exposed in client-side code.
|
|
|
|
For Kubernetes deployments, you can use the secret reference format:
|
|
urn:k8s:secret:namespace:secret-name:key
|
|
required: true
|
|
|
|
callbackURL:
|
|
type: string
|
|
description: |
|
|
The path where the OIDC provider will redirect after authentication.
|
|
This must match one of the redirect URIs configured in your OIDC provider.
|
|
|
|
The full redirect URI will be constructed as:
|
|
[scheme]://[host][callbackURL]
|
|
|
|
Example: /oauth2/callback
|
|
required: true
|
|
|
|
sessionEncryptionKey:
|
|
type: string
|
|
description: |
|
|
Key used to encrypt session data stored in cookies.
|
|
Must be at least 32 bytes long for security.
|
|
|
|
Example: potato-secret-is-at-least-32-bytes-long
|
|
required: true
|
|
|
|
logoutURL:
|
|
type: string
|
|
description: |
|
|
The path for handling logout requests.
|
|
If not provided, it will be set to callbackURL + "/logout".
|
|
|
|
Example: /oauth2/logout
|
|
required: false
|
|
|
|
postLogoutRedirectURI:
|
|
type: string
|
|
description: |
|
|
The URL to redirect to after logout.
|
|
Default: "/"
|
|
|
|
Example: /logged-out-page
|
|
required: false
|
|
|
|
scopes:
|
|
type: array
|
|
description: |
|
|
Additional OAuth 2.0 scopes to append to the default scopes.
|
|
Default scopes are always included: ["openid", "profile", "email"]
|
|
|
|
User-provided scopes are appended to defaults with automatic deduplication.
|
|
For example, specifying ["roles", "custom_scope"] results in:
|
|
["openid", "profile", "email", "roles", "custom_scope"]
|
|
|
|
Include "roles" or similar scope if you need role/group information.
|
|
Note: For Google OAuth, the middleware automatically handles the
|
|
proper authentication parameters and does NOT require the "offline_access"
|
|
scope (which Google rejects as invalid). See documentation for details.
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
logLevel:
|
|
type: string
|
|
description: |
|
|
Sets the logging verbosity.
|
|
Valid values: "debug", "info", "error"
|
|
Default: "info"
|
|
required: false
|
|
enum:
|
|
- debug
|
|
- info
|
|
- error
|
|
|
|
forceHTTPS:
|
|
type: boolean
|
|
description: |
|
|
Forces HTTPS scheme for redirect URIs regardless of request headers or TLS state.
|
|
|
|
⚠️ CRITICAL CONFIGURATION for TLS Termination Scenarios:
|
|
|
|
When running Traefik behind a load balancer that terminates TLS (AWS ALB,
|
|
Google Cloud Load Balancer, Azure Application Gateway, etc.), you MUST set
|
|
this to true. Without it, redirect URIs will use http:// instead of https://,
|
|
causing OAuth callback failures.
|
|
|
|
How it works:
|
|
- When true: Always uses https:// for redirect URIs (highest priority)
|
|
- When false: Detects scheme from X-Forwarded-Proto header or TLS state
|
|
- When NOT specified: Defaults to false (Go zero value for bool)
|
|
|
|
Default: false (when not specified in configuration)
|
|
Recommended: true (for production environments and TLS termination scenarios)
|
|
|
|
See: https://github.com/lukaszraczylo/traefikoidc/issues/82
|
|
required: false
|
|
|
|
rateLimit:
|
|
type: integer
|
|
description: |
|
|
Sets the maximum number of requests per second.
|
|
This helps prevent brute force attacks.
|
|
Default: 100
|
|
Minimum: 10
|
|
required: false
|
|
|
|
excludedURLs:
|
|
type: array
|
|
description: |
|
|
Lists paths that bypass authentication.
|
|
These paths will be accessible without OIDC authentication.
|
|
|
|
The middleware uses prefix matching, so "/public" will match
|
|
"/public", "/public/page", "/public-data", etc.
|
|
|
|
Examples: ["/health", "/metrics", "/public"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
allowedUserDomains:
|
|
type: array
|
|
description: |
|
|
Restricts access to users with email addresses from specific domains.
|
|
If not provided, the middleware relies entirely on the OIDC provider
|
|
for authentication decisions.
|
|
|
|
Examples: ["company.com", "subsidiary.com"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
allowedUsers:
|
|
type: array
|
|
description: |
|
|
Restricts access to specific email addresses.
|
|
If provided, only users with these exact email addresses will be allowed access,
|
|
in addition to any domain-level restrictions set by allowedUserDomains.
|
|
|
|
This provides fine-grained control over individual access and can be used
|
|
together with allowedUserDomains for flexible access control strategies.
|
|
|
|
Examples: ["user1@example.com", "admin@company.com"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
allowedRolesAndGroups:
|
|
type: array
|
|
description: |
|
|
Restricts access to users with specific roles or groups.
|
|
If not provided, no role/group restrictions are applied.
|
|
|
|
The middleware checks both the "roles" and "groups" claims in the ID token.
|
|
|
|
Examples: ["admin", "developer"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
revocationURL:
|
|
type: string
|
|
description: |
|
|
The endpoint for revoking tokens.
|
|
If not provided, it will be discovered from provider metadata.
|
|
|
|
Example: https://accounts.google.com/revoke
|
|
required: false
|
|
|
|
oidcEndSessionURL:
|
|
type: string
|
|
description: |
|
|
The provider's end session endpoint.
|
|
If not provided, it will be discovered from provider metadata.
|
|
|
|
Example: https://accounts.google.com/logout
|
|
required: false
|
|
|
|
enablePKCE:
|
|
type: boolean
|
|
description: |
|
|
Enables PKCE (Proof Key for Code Exchange) for the OAuth 2.0 authorization code flow.
|
|
PKCE adds an extra layer of security to protect against authorization code interception attacks.
|
|
|
|
Not all OIDC providers support PKCE, so this should only be enabled if your provider supports it.
|
|
If enabled, the middleware will generate and use a code verifier/challenge pair during authentication.
|
|
|
|
Default: false
|
|
required: false
|
|
|
|
cookieDomain:
|
|
type: string
|
|
description: |
|
|
Explicit domain for session cookies. This is important for multi-subdomain setups
|
|
and reverse proxy deployments to ensure consistent cookie handling.
|
|
|
|
When set, all session cookies will use this domain. When not set, the domain
|
|
is auto-detected from the request headers (X-Forwarded-Host or Host).
|
|
|
|
Use a leading dot for subdomain-wide cookies (e.g., ".example.com" allows
|
|
cookies to be shared between app.example.com, api.example.com, etc.).
|
|
|
|
Use a specific domain for host-only cookies (e.g., "app.example.com" restricts
|
|
cookies to that exact domain).
|
|
|
|
This setting is crucial to prevent authentication issues like "CSRF token missing
|
|
in session" errors that can occur when cookies are created with inconsistent domains.
|
|
|
|
Examples:
|
|
- ".example.com" - Allows all subdomains to share cookies
|
|
- "app.example.com" - Restricts cookies to this specific host
|
|
|
|
Default: "" (auto-detected from request headers)
|
|
required: false
|
|
|
|
cookiePrefix:
|
|
type: string
|
|
description: |
|
|
Custom prefix for session cookie names. This is essential for running multiple
|
|
middleware instances with different authorization requirements on the same domain.
|
|
|
|
By default, all middleware instances use the same cookie names (_oidc_raczylo_m,
|
|
_oidc_raczylo_a, etc.), which means they share session state. When you have
|
|
multiple instances with different access restrictions (e.g., one for general users
|
|
and one for admins), this session sharing can lead to authorization bypass issues.
|
|
|
|
Setting a unique cookiePrefix for each middleware instance ensures complete
|
|
session isolation, preventing users authenticated via one middleware from
|
|
automatically gaining access to routes protected by a different middleware.
|
|
|
|
The prefix is prepended to all session cookie names:
|
|
- Main session cookie: {prefix}m
|
|
- Access token cookie: {prefix}a
|
|
- Refresh token cookie: {prefix}r
|
|
- ID token cookie: {prefix}id
|
|
|
|
Examples:
|
|
- "_oidc_userauth_" - For general user authentication middleware
|
|
- "_oidc_adminauth_" - For admin-only authentication middleware
|
|
- "_oidc_api_" - For API-specific authentication middleware
|
|
|
|
Security Note: Use different cookie prefixes AND different sessionEncryptionKey
|
|
values for each middleware instance to ensure complete isolation.
|
|
|
|
Default: "_oidc_raczylo_" (standard prefix for backward compatibility)
|
|
|
|
See: https://github.com/lukaszraczylo/traefikoidc/issues/87
|
|
required: false
|
|
|
|
sessionMaxAge:
|
|
type: integer
|
|
description: |
|
|
Maximum session age in seconds before requiring re-authentication.
|
|
|
|
This setting controls how long a user's authentication session remains valid
|
|
before they must authenticate again through the OIDC provider. The session
|
|
age is tracked from the initial authentication time (created_at).
|
|
|
|
When a session exceeds this age:
|
|
- The session is cleared and invalidated
|
|
- The user is redirected to re-authenticate
|
|
- All session cookies are removed
|
|
|
|
Use Cases:
|
|
- High-security applications: Use shorter durations (e.g., 3600 = 1 hour)
|
|
- Standard applications: Default 24 hours balances security and UX
|
|
- Long-lived sessions: Extend for applications accessed infrequently
|
|
(e.g., 604800 = 7 days, 2592000 = 30 days)
|
|
|
|
Security Considerations:
|
|
- Shorter sessions provide better security but require more frequent logins
|
|
- Longer sessions improve user experience but increase security risk
|
|
- Consider your application's security requirements and user access patterns
|
|
- This is independent of token refresh - tokens can be refreshed during the session
|
|
|
|
Common Values:
|
|
- 3600 (1 hour) - High security applications
|
|
- 28800 (8 hours) - Working day session
|
|
- 86400 (24 hours) - Default, balances security and convenience
|
|
- 604800 (7 days) - Weekly session for less frequently accessed apps
|
|
- 2592000 (30 days) - Monthly session for infrequently used applications
|
|
|
|
Default: 86400 (24 hours)
|
|
Minimum: 0 (uses default of 24 hours)
|
|
|
|
See: https://github.com/lukaszraczylo/traefikoidc/issues/91
|
|
required: false
|
|
|
|
overrideScopes:
|
|
type: boolean
|
|
description: |
|
|
When set to true, the scopes you provide will completely replace the default scopes
|
|
(openid, profile, email) instead of being appended to them.
|
|
|
|
This is useful when you need precise control over the scopes sent to the OIDC provider,
|
|
such as when a provider requires specific scopes or when you want to minimize the
|
|
requested permissions.
|
|
|
|
Default: false (appends user scopes to defaults)
|
|
required: false
|
|
|
|
refreshGracePeriodSeconds:
|
|
type: integer
|
|
description: |
|
|
The number of seconds before a token expires to attempt proactive refresh.
|
|
|
|
When a request is made and the access token will expire within this grace period,
|
|
the middleware will attempt to refresh the token proactively. This helps prevent
|
|
authentication interruptions for active users.
|
|
|
|
Setting this to 0 disables proactive refresh (tokens are only refreshed after expiry).
|
|
|
|
Default: 60 (1 minute before expiry)
|
|
required: false
|
|
|
|
audience:
|
|
type: string
|
|
description: |
|
|
Custom audience value for access token validation.
|
|
|
|
This configures the expected audience claim in access tokens. Per OAuth 2.0 and OIDC
|
|
specifications:
|
|
- ID tokens always have aud=client_id (per OIDC Core 1.0)
|
|
- Access tokens can have custom audiences (e.g., API identifiers)
|
|
|
|
Auth0 Scenarios:
|
|
1. Custom API audience (recommended): Set to your API identifier from Auth0
|
|
Example: "https://my-api.example.com"
|
|
Result: Access tokens will contain this audience
|
|
|
|
2. Default audience: Leave empty or omit (uses client_id)
|
|
Result: Access tokens may not contain client_id, triggering warnings
|
|
|
|
3. Opaque tokens: Use with allowOpaqueTokens=true for non-JWT tokens
|
|
|
|
When configured and different from client_id, the middleware automatically adds
|
|
the audience parameter to the authorize endpoint request.
|
|
|
|
Default: "" (uses client_id as audience)
|
|
See: AUTH0_AUDIENCE_GUIDE.md for detailed configuration
|
|
required: false
|
|
|
|
strictAudienceValidation:
|
|
type: boolean
|
|
description: |
|
|
Enforce strict audience validation for access tokens.
|
|
|
|
When enabled, sessions are rejected if access token validation fails due to
|
|
audience mismatch. This prevents falling back to ID token validation, addressing
|
|
potential token confusion attacks where tokens intended for different APIs could
|
|
be used to grant access.
|
|
|
|
Auth0 Scenario 2 Protection:
|
|
- When true: Rejects sessions with mismatched access token audience
|
|
- When false: Logs security warnings but allows fallback to ID token (backward compatible)
|
|
|
|
Security Recommendation:
|
|
- Production environments: Set to true for maximum security
|
|
- Development/testing: Can use false with monitoring of security warnings
|
|
|
|
This setting addresses security concerns where access tokens without proper
|
|
audience claims could bypass API-specific authorization checks.
|
|
|
|
Default: false (backward compatible)
|
|
See: https://github.com/lukaszraczylo/traefikoidc/issues/74
|
|
required: false
|
|
|
|
allowOpaqueTokens:
|
|
type: boolean
|
|
description: |
|
|
Enable acceptance of opaque (non-JWT) access tokens.
|
|
|
|
When enabled, the middleware accepts access tokens that are not in JWT format
|
|
(3-part base64 structure). Opaque tokens are validated using OAuth 2.0 Token
|
|
Introspection (RFC 7662) if the provider exposes an introspection endpoint.
|
|
|
|
Auth0 Scenario 3:
|
|
Some Auth0 configurations issue opaque access tokens when no default API is
|
|
configured. This setting allows those tokens to be validated.
|
|
|
|
Requirements:
|
|
- Provider must support introspection_endpoint in OIDC discovery
|
|
- Client must have appropriate introspection permissions
|
|
|
|
Validation Process:
|
|
1. Detects opaque token (not 3-part JWT structure)
|
|
2. Calls provider's introspection endpoint with client credentials
|
|
3. Validates response (active status, expiration, audience if present)
|
|
4. Caches result for 5 minutes or token expiry (whichever is shorter)
|
|
5. Falls back to ID token validation if introspection unavailable
|
|
(unless requireTokenIntrospection=true)
|
|
|
|
Default: false (only JWT access tokens accepted)
|
|
See: AUTH0_AUDIENCE_GUIDE.md for configuration examples
|
|
required: false
|
|
|
|
requireTokenIntrospection:
|
|
type: boolean
|
|
description: |
|
|
Require token introspection for all opaque access tokens.
|
|
|
|
When enabled with allowOpaqueTokens=true, opaque tokens are rejected if:
|
|
- Introspection endpoint is not available from provider metadata
|
|
- Introspection request fails
|
|
- Introspection response indicates token is not active
|
|
|
|
Security Levels:
|
|
- requireTokenIntrospection=true + allowOpaqueTokens=true:
|
|
Maximum security - rejects opaque tokens without successful introspection
|
|
|
|
- requireTokenIntrospection=false + allowOpaqueTokens=true:
|
|
Backward compatible - falls back to ID token validation if introspection fails
|
|
|
|
- requireTokenIntrospection=true + allowOpaqueTokens=false:
|
|
No effect - opaque tokens are already rejected
|
|
|
|
Recommended Configuration:
|
|
When accepting opaque tokens, always set this to true for maximum security:
|
|
```yaml
|
|
allowOpaqueTokens: true
|
|
requireTokenIntrospection: true
|
|
```
|
|
|
|
Default: false (allows fallback to ID token)
|
|
See: RFC 7662 OAuth 2.0 Token Introspection specification
|
|
required: false
|
|
|
|
disableReplayDetection:
|
|
type: boolean
|
|
description: |
|
|
Disable JTI-based replay attack detection for multi-replica deployments.
|
|
|
|
When running multiple Traefik replicas, each instance maintains its own in-memory
|
|
JTI (JWT Token ID) cache. This causes false positives when the same valid token
|
|
hits different replicas:
|
|
- Request → Replica A → JTI added to cache → OK
|
|
- Request → Replica B → JTI not in Replica B's cache → OK
|
|
- Request → Replica A again → JTI found → FALSE POSITIVE "replay detected"
|
|
|
|
Security Impact:
|
|
When disabled, the following validations remain active:
|
|
- RSA/ECDSA signature verification
|
|
- Token expiration (exp claim)
|
|
- Issuer validation (iss claim)
|
|
- Audience validation (aud claim)
|
|
- Not-before validation (nbf claim)
|
|
- Issued-at validation (iat claim)
|
|
|
|
Only the JTI replay check is skipped.
|
|
|
|
Recommendations:
|
|
- Single-instance deployment: false (default, enables replay protection)
|
|
- Multi-replica deployment: true (prevents false positives)
|
|
- Production with shared cache: false (use Redis/Memcached for shared JTI cache)
|
|
|
|
Default: false (replay detection enabled)
|
|
required: false
|
|
|
|
headers:
|
|
type: array
|
|
description: |
|
|
Custom HTTP headers to set with templated values derived from OIDC claims and tokens.
|
|
Each header has a name and a value template that can access:
|
|
- {{.Claims.field}} - Access ID token claims (e.g., email, sub, name)
|
|
- {{.AccessToken}} - The raw access token string
|
|
- {{.IdToken}} - The raw ID token string
|
|
- {{.RefreshToken}} - The raw refresh token string
|
|
|
|
Templates support Go template syntax including conditionals and iteration.
|
|
Variable names are case-sensitive - use .Claims not .claims.
|
|
|
|
IMPORTANT: Template Escaping
|
|
If you encounter the error "can't evaluate field AccessToken in type bool" when
|
|
starting Traefik, this means Traefik is trying to evaluate the template expressions
|
|
before passing them to the plugin.
|
|
|
|
SOLUTION: You must escape the template expressions using double curly braces:
|
|
|
|
headers:
|
|
- name: "Authorization"
|
|
value: "Bearer {{{{.AccessToken}}}}"
|
|
|
|
This is the only reliable method that works consistently. Here's why:
|
|
- The YAML parser converts {{{{ → {{ and }}}} → }}
|
|
- Result: Bearer {{.AccessToken}} reaches the Go template engine correctly
|
|
- Other methods (YAML literal style, single quotes) do NOT work reliably
|
|
|
|
Examples:
|
|
- name: "X-User-Email", value: "{{{{.Claims.email}}}}"
|
|
- name: "Authorization", value: "Bearer {{{{.AccessToken}}}}"
|
|
- name: "X-User-Roles", value: "{{{{range $i, $e := .Claims.roles}}}}{{{{if $i}}}},{{{{end}}}}{{{{$e}}}}{{{{end}}}}"
|
|
required: false
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: The HTTP header name to set
|
|
value:
|
|
type: string
|
|
description: Template string for the header value
|
|
|
|
securityHeaders:
|
|
type: object
|
|
description: |
|
|
Configuration for security headers to protect against common web vulnerabilities.
|
|
Security headers are applied to all authenticated responses.
|
|
|
|
The middleware includes comprehensive security headers support with multiple profiles:
|
|
- default: Balanced security for standard web applications
|
|
- strict: Maximum security for high-security applications
|
|
- development: Relaxed policies for local development
|
|
- api: API-friendly configuration with CORS support
|
|
- custom: Full control over all security header settings
|
|
|
|
Security features include:
|
|
- Content Security Policy (CSP) to prevent XSS attacks
|
|
- HTTP Strict Transport Security (HSTS) to enforce HTTPS
|
|
- Frame Options to prevent clickjacking
|
|
- XSS Protection for browser-level filtering
|
|
- Content Type Options to prevent MIME sniffing
|
|
- CORS headers for cross-origin resource sharing
|
|
- Custom headers for additional security requirements
|
|
|
|
Example configurations:
|
|
|
|
Basic security (recommended):
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: "default"
|
|
|
|
API with CORS:
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: "api"
|
|
corsEnabled: true
|
|
corsAllowedOrigins: ["https://app.example.com"]
|
|
|
|
Custom configuration:
|
|
securityHeaders:
|
|
enabled: true
|
|
profile: "custom"
|
|
contentSecurityPolicy: "default-src 'self'"
|
|
corsEnabled: true
|
|
corsAllowedOrigins: ["https://*.example.com"]
|
|
customHeaders:
|
|
X-Security-Level: "high"
|
|
required: false
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: |
|
|
Enable or disable security headers.
|
|
When disabled, only basic fallback headers are applied.
|
|
Default: true
|
|
required: false
|
|
|
|
profile:
|
|
type: string
|
|
description: |
|
|
Security profile to use. Each profile provides a different balance of security and functionality:
|
|
|
|
- default: Balanced security suitable for most web applications
|
|
- strict: Maximum security with very restrictive policies
|
|
- development: Relaxed policies for local development (enables localhost CORS)
|
|
- api: API-friendly configuration with configurable CORS
|
|
- custom: No defaults, use only explicitly configured settings
|
|
|
|
Default: "default"
|
|
required: false
|
|
enum:
|
|
- default
|
|
- strict
|
|
- development
|
|
- api
|
|
- custom
|
|
|
|
contentSecurityPolicy:
|
|
type: string
|
|
description: |
|
|
Content Security Policy header value to prevent XSS and code injection attacks.
|
|
Only applied when using "custom" profile or to override profile defaults.
|
|
|
|
Examples:
|
|
- "default-src 'self'" (strict)
|
|
- "default-src 'self'; script-src 'self' 'unsafe-inline'" (moderate)
|
|
- "default-src 'self' 'unsafe-inline' 'unsafe-eval'" (permissive)
|
|
required: false
|
|
|
|
strictTransportSecurity:
|
|
type: boolean
|
|
description: |
|
|
Enable HTTP Strict Transport Security (HSTS) to force HTTPS connections.
|
|
Only applied when HTTPS is detected (via TLS or X-Forwarded-Proto header).
|
|
Default: true
|
|
required: false
|
|
|
|
strictTransportSecurityMaxAge:
|
|
type: integer
|
|
description: |
|
|
HSTS max-age value in seconds. Determines how long browsers should enforce HTTPS.
|
|
Common values:
|
|
- 31536000 (1 year) - recommended for production
|
|
- 86400 (1 day) - for testing
|
|
Default: 31536000
|
|
required: false
|
|
|
|
strictTransportSecuritySubdomains:
|
|
type: boolean
|
|
description: |
|
|
Include subdomains in HSTS policy.
|
|
When true, HSTS applies to all subdomains of the current domain.
|
|
Default: true
|
|
required: false
|
|
|
|
strictTransportSecurityPreload:
|
|
type: boolean
|
|
description: |
|
|
Enable HSTS preload list eligibility.
|
|
Allows the domain to be included in browser HSTS preload lists.
|
|
Default: true
|
|
required: false
|
|
|
|
frameOptions:
|
|
type: string
|
|
description: |
|
|
X-Frame-Options header value to prevent clickjacking attacks.
|
|
|
|
Options:
|
|
- DENY: Prevents framing completely
|
|
- SAMEORIGIN: Allows framing only from the same origin
|
|
- ALLOW-FROM uri: Allows framing from specific URI
|
|
|
|
Default: "DENY"
|
|
required: false
|
|
|
|
contentTypeOptions:
|
|
type: string
|
|
description: |
|
|
X-Content-Type-Options header value to prevent MIME type sniffing.
|
|
Should typically be set to "nosniff".
|
|
Default: "nosniff"
|
|
required: false
|
|
|
|
xssProtection:
|
|
type: string
|
|
description: |
|
|
X-XSS-Protection header value for browser XSS filtering.
|
|
Recommended value: "1; mode=block"
|
|
Default: "1; mode=block"
|
|
required: false
|
|
|
|
referrerPolicy:
|
|
type: string
|
|
description: |
|
|
Referrer-Policy header value to control referrer information sharing.
|
|
|
|
Common values:
|
|
- strict-origin-when-cross-origin (recommended)
|
|
- no-referrer (most restrictive)
|
|
- same-origin (moderate)
|
|
|
|
Default: "strict-origin-when-cross-origin"
|
|
required: false
|
|
|
|
corsEnabled:
|
|
type: boolean
|
|
description: |
|
|
Enable Cross-Origin Resource Sharing (CORS) headers.
|
|
Essential for API endpoints that need to be accessed from web browsers.
|
|
Default: false
|
|
required: false
|
|
|
|
corsAllowedOrigins:
|
|
type: array
|
|
description: |
|
|
List of allowed origins for CORS requests.
|
|
Supports wildcards for flexible origin matching:
|
|
|
|
- "https://example.com" (exact match)
|
|
- "https://*.example.com" (subdomain wildcard)
|
|
- "http://localhost:*" (port wildcard, useful for development)
|
|
- "*" (allow all origins - not recommended for production)
|
|
|
|
Examples: ["https://app.example.com", "https://*.api.example.com"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
corsAllowedMethods:
|
|
type: array
|
|
description: |
|
|
HTTP methods allowed for CORS requests.
|
|
Default: ["GET", "POST", "OPTIONS"]
|
|
|
|
Common additions: ["PUT", "DELETE", "PATCH"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
corsAllowedHeaders:
|
|
type: array
|
|
description: |
|
|
HTTP headers allowed for CORS requests.
|
|
Default: ["Authorization", "Content-Type"]
|
|
|
|
Common additions: ["X-Requested-With", "X-API-Key"]
|
|
required: false
|
|
items:
|
|
type: string
|
|
|
|
corsAllowCredentials:
|
|
type: boolean
|
|
description: |
|
|
Allow credentials (cookies, authorization headers) in CORS requests.
|
|
Required for authenticated API requests from browsers.
|
|
Default: false
|
|
required: false
|
|
|
|
corsMaxAge:
|
|
type: integer
|
|
description: |
|
|
Maximum age in seconds for CORS preflight cache.
|
|
Reduces preflight request frequency for better performance.
|
|
Default: 86400 (24 hours)
|
|
required: false
|
|
|
|
customHeaders:
|
|
type: object
|
|
description: |
|
|
Additional custom headers to include in responses.
|
|
Useful for application-specific security requirements.
|
|
|
|
Examples:
|
|
X-Security-Level: "high"
|
|
X-API-Version: "v1"
|
|
X-Environment: "production"
|
|
required: false
|
|
|
|
disableServerHeader:
|
|
type: boolean
|
|
description: |
|
|
Remove the Server header to hide server information.
|
|
Recommended for security through obscurity.
|
|
Default: true
|
|
required: false
|
|
|
|
disablePoweredByHeader:
|
|
type: boolean
|
|
description: |
|
|
Remove the X-Powered-By header to hide technology stack information.
|
|
Default: true
|
|
required: false
|
|
|
|
permissionsPolicy:
|
|
type: string
|
|
description: |
|
|
Permissions-Policy header to control browser feature permissions.
|
|
This header allows you to control which features and APIs can be used.
|
|
|
|
Examples:
|
|
- "geolocation=(), camera=(), microphone=()" (deny all)
|
|
- "geolocation=(self), camera=()" (allow geolocation for same origin only)
|
|
|
|
Common directives: accelerometer, camera, geolocation, gyroscope,
|
|
magnetometer, microphone, payment, usb
|
|
required: false
|
|
|
|
crossOriginEmbedderPolicy:
|
|
type: string
|
|
description: |
|
|
Cross-Origin-Embedder-Policy (COEP) header to prevent untrusted
|
|
resources from being loaded.
|
|
|
|
Options:
|
|
- "require-corp": Resources must explicitly grant permission
|
|
- "credentialless": Load without credentials for cross-origin resources
|
|
- "unsafe-none": No restrictions (default)
|
|
|
|
Required for certain browser features like SharedArrayBuffer.
|
|
required: false
|
|
|
|
crossOriginOpenerPolicy:
|
|
type: string
|
|
description: |
|
|
Cross-Origin-Opener-Policy (COOP) header to isolate browsing context
|
|
from cross-origin windows.
|
|
|
|
Options:
|
|
- "same-origin": Isolate from cross-origin documents
|
|
- "same-origin-allow-popups": Allow popups that don't set COOP
|
|
- "unsafe-none": No isolation (default)
|
|
|
|
Helps prevent cross-origin attacks and Spectre-like vulnerabilities.
|
|
required: false
|
|
|
|
crossOriginResourcePolicy:
|
|
type: string
|
|
description: |
|
|
Cross-Origin-Resource-Policy (CORP) header to control which origins
|
|
can load this resource.
|
|
|
|
Options:
|
|
- "same-origin": Only same-origin requests can load the resource
|
|
- "same-site": Only same-site requests can load the resource
|
|
- "cross-origin": Any origin can load the resource (default)
|
|
|
|
Prevents your resources from being embedded on other sites.
|
|
required: false
|
|
|
|
redis:
|
|
type: object
|
|
description: |
|
|
Optional Redis cache configuration for multi-replica deployments.
|
|
|
|
When running multiple Traefik instances, Redis provides shared caching to:
|
|
- Prevent JTI replay detection false positives across replicas
|
|
- Share token verification results between instances
|
|
- Maintain consistent session state across the cluster
|
|
- Improve performance by reducing redundant OIDC provider calls
|
|
|
|
Features:
|
|
- Automatic failover to memory-only mode when Redis is unavailable
|
|
- Circuit breaker pattern for resilience against Redis failures
|
|
- Health checking with automatic recovery
|
|
- Multiple cache modes: redis-only, hybrid (L1 memory + L2 Redis), memory-only
|
|
- Configurable timeouts and connection pooling
|
|
- TLS support for secure Redis connections
|
|
|
|
The middleware gracefully handles Redis failures by falling back to in-memory
|
|
caching, ensuring your authentication flow continues even during Redis outages.
|
|
|
|
Example configuration:
|
|
```yaml
|
|
redis:
|
|
enabled: true
|
|
address: "redis:6379"
|
|
cacheMode: "hybrid"
|
|
enableCircuitBreaker: true
|
|
```
|
|
required: false
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: |
|
|
Enable Redis caching for distributed session and token management.
|
|
When enabled, the middleware will attempt to connect to Redis and use it
|
|
for shared state across multiple Traefik instances.
|
|
|
|
Default: false
|
|
required: false
|
|
|
|
address:
|
|
type: string
|
|
description: |
|
|
Redis server address in host:port format.
|
|
|
|
Examples:
|
|
- "redis:6379" (Docker/Kubernetes service)
|
|
- "localhost:6379" (local Redis)
|
|
- "redis.example.com:6380" (custom host/port)
|
|
- "redis-cluster.default.svc.cluster.local:6379" (Kubernetes)
|
|
|
|
Required when Redis is enabled.
|
|
required: false
|
|
|
|
password:
|
|
type: string
|
|
description: |
|
|
Password for Redis authentication.
|
|
Leave empty if Redis doesn't require authentication.
|
|
|
|
For Kubernetes deployments, you can use secret references:
|
|
urn:k8s:secret:namespace:secret-name:key
|
|
|
|
Default: "" (no authentication)
|
|
required: false
|
|
|
|
db:
|
|
type: integer
|
|
description: |
|
|
Redis database number to use (0-15).
|
|
Different databases can be used to isolate data between environments.
|
|
|
|
Default: 0
|
|
required: false
|
|
|
|
keyPrefix:
|
|
type: string
|
|
description: |
|
|
Prefix for all Redis keys created by this middleware.
|
|
Useful for:
|
|
- Avoiding key collisions with other applications
|
|
- Identifying keys for monitoring/debugging
|
|
- Supporting multiple environments in the same Redis instance
|
|
|
|
Default: "traefikoidc:"
|
|
required: false
|
|
|
|
cacheMode:
|
|
type: string
|
|
description: |
|
|
Determines the caching strategy:
|
|
|
|
- "redis": Redis-only caching. All cache operations go directly to Redis.
|
|
Best for: Consistent state across all replicas, minimal memory usage.
|
|
|
|
- "hybrid": Two-tier caching with in-memory L1 and Redis L2.
|
|
Best for: High performance with shared state, reduced Redis load.
|
|
L1 provides fast local cache, L2 provides shared state.
|
|
|
|
- "memory": Memory-only caching (Redis disabled even if configured).
|
|
Best for: Single instance deployments, development/testing.
|
|
|
|
Default: "redis" (when Redis is enabled)
|
|
required: false
|
|
enum:
|
|
- redis
|
|
- hybrid
|
|
- memory
|
|
|
|
poolSize:
|
|
type: integer
|
|
description: |
|
|
Maximum number of socket connections to Redis.
|
|
Higher values allow more concurrent operations but consume more resources.
|
|
|
|
Recommendations:
|
|
- Small deployments: 10-20
|
|
- Medium deployments: 20-50
|
|
- Large deployments: 50-100
|
|
|
|
Default: 10
|
|
required: false
|
|
|
|
connectTimeout:
|
|
type: integer
|
|
description: |
|
|
Timeout in seconds for establishing new connections to Redis.
|
|
Should be higher than network latency but low enough to fail fast.
|
|
|
|
Default: 5 seconds
|
|
required: false
|
|
|
|
readTimeout:
|
|
type: integer
|
|
description: |
|
|
Timeout in seconds for Redis read operations.
|
|
Includes the time to send the command, wait for Redis to process it,
|
|
and receive the response.
|
|
|
|
Default: 3 seconds
|
|
required: false
|
|
|
|
writeTimeout:
|
|
type: integer
|
|
description: |
|
|
Timeout in seconds for Redis write operations.
|
|
Should account for network latency and Redis persistence settings.
|
|
|
|
Default: 3 seconds
|
|
required: false
|
|
|
|
enableTLS:
|
|
type: boolean
|
|
description: |
|
|
Enable TLS encryption for Redis connections.
|
|
Required when connecting to Redis instances that enforce TLS,
|
|
such as AWS ElastiCache with encryption in transit.
|
|
|
|
Default: false
|
|
required: false
|
|
|
|
tlsSkipVerify:
|
|
type: boolean
|
|
description: |
|
|
Skip TLS certificate verification for Redis connections.
|
|
|
|
⚠️ WARNING: Only use in development environments.
|
|
This option bypasses certificate validation and should never be used
|
|
in production as it's vulnerable to man-in-the-middle attacks.
|
|
|
|
Default: false
|
|
required: false
|
|
|
|
hybridL1Size:
|
|
type: integer
|
|
description: |
|
|
Maximum number of items in the L1 (in-memory) cache for hybrid mode.
|
|
Controls how many cache entries are kept in local memory before eviction.
|
|
|
|
Only applies when cacheMode is "hybrid".
|
|
|
|
Default: 500
|
|
required: false
|
|
|
|
hybridL1MemoryMB:
|
|
type: integer
|
|
description: |
|
|
Maximum memory in megabytes for L1 cache in hybrid mode.
|
|
The cache will start evicting items when this limit is approached.
|
|
|
|
Only applies when cacheMode is "hybrid".
|
|
|
|
Default: 10 MB
|
|
required: false
|
|
|
|
enableCircuitBreaker:
|
|
type: boolean
|
|
description: |
|
|
Enable circuit breaker pattern for Redis connection failures.
|
|
|
|
When enabled, the middleware will:
|
|
1. Track Redis operation failures
|
|
2. Open the circuit after threshold failures (stop trying Redis)
|
|
3. Fall back to in-memory caching
|
|
4. Periodically attempt to reconnect (half-open state)
|
|
5. Resume Redis operations when connection recovers
|
|
|
|
This prevents cascading failures and improves resilience.
|
|
|
|
Default: true
|
|
required: false
|
|
|
|
circuitBreakerThreshold:
|
|
type: integer
|
|
description: |
|
|
Number of consecutive Redis failures before opening the circuit.
|
|
Lower values make the system more sensitive to Redis issues,
|
|
higher values tolerate more failures before switching to fallback.
|
|
|
|
Default: 5
|
|
required: false
|
|
|
|
circuitBreakerTimeout:
|
|
type: integer
|
|
description: |
|
|
Time in seconds to wait before attempting to close the circuit.
|
|
After this timeout, the circuit breaker will allow one test request
|
|
to Redis. If successful, normal operations resume.
|
|
|
|
Default: 60 seconds
|
|
required: false
|
|
|
|
enableHealthCheck:
|
|
type: boolean
|
|
description: |
|
|
Enable periodic health checks for Redis connection.
|
|
|
|
Health checks:
|
|
- Run in the background at regular intervals
|
|
- Detect Redis availability without affecting request processing
|
|
- Automatically reconnect when Redis becomes available
|
|
- Update circuit breaker state based on health status
|
|
|
|
Default: true
|
|
required: false
|
|
|
|
healthCheckInterval:
|
|
type: integer
|
|
description: |
|
|
Interval in seconds between Redis health checks.
|
|
Lower values detect issues faster but increase Redis load.
|
|
Higher values reduce overhead but delay failure detection.
|
|
|
|
Default: 30 seconds
|
|
required: false
|