mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-14 04:07:46 +00:00
425 lines
16 KiB
YAML
425 lines
16 KiB
YAML
displayName: Traefik OIDC
|
|
type: middleware
|
|
|
|
import: github.com/lukaszraczylo/traefikoidc
|
|
|
|
summary: |
|
|
Middleware adding OpenID Connect (OIDC) authentication to Traefik routes.
|
|
|
|
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 like domain restrictions,
|
|
role-based access control, token caching, and more.
|
|
|
|
The middleware has been tested with Auth0, Logto, Google, and other standard OIDC providers.
|
|
It includes special handling for Google's OAuth implementation to ensure compatibility.
|
|
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
|
|
- Public URLs that bypass authentication
|
|
- Rate limiting to prevent brute force attacks
|
|
- Custom post-logout redirect behavior
|
|
- Secure session management with encrypted cookies
|
|
- Automatic token validation and refresh
|
|
|
|
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
|
|
- [email protected]
|
|
- [email protected]
|
|
|
|
allowedRolesAndGroups: # Restricts access to users with specific roles or groups (if not provided, no role/group restrictions)
|
|
- guest-endpoints
|
|
- admin
|
|
- developer
|
|
|
|
forceHTTPS: false # Forces the use of HTTPS for all URLs (default: true for security)
|
|
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: If you encounter "can't evaluate field AccessToken in type bool" errors,
|
|
# you may need to escape the templates. See the headers section in configuration below.
|
|
- 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
|
|
|
|
# --- Provider Specific Configuration Examples ---
|
|
#
|
|
# Below are example configurations tailored for specific OIDC providers.
|
|
# Uncomment and adapt the relevant section for your provider.
|
|
# Remember to replace placeholder values (like client IDs, secrets, domains)
|
|
# with your actual credentials and settings.
|
|
#
|
|
# 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 # This is standard for Google
|
|
# 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: # Defaults ["openid", "profile", "email"] are handled. Plugin manages Google-specifics.
|
|
# # Do NOT add 'offline_access' - plugin handles this.
|
|
# allowedUserDomains: # Useful for Google Workspace users
|
|
# - your-gsuite-domain.com
|
|
# # Google includes 'hd' (hosted domain) claim which can be used with allowedUserDomains.
|
|
# # Other claims like 'email', 'sub', 'name' are standard.
|
|
# # See README.md "Provider Configuration Recommendations" for Google.
|
|
|
|
# --- 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"
|
|
# 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".
|
|
# # See README.md "Provider Configuration Recommendations" for Auth0.
|
|
|
|
# --- 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.
|
|
|
|
Examples:
|
|
- https://accounts.google.com
|
|
- https://login.microsoftonline.com/tenant-id/v2.0
|
|
- https://your-auth0-domain.auth0.com
|
|
- https://your-logto-instance.com/oidc
|
|
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 the use of HTTPS for all URLs.
|
|
This is recommended for security in production environments.
|
|
Default: true
|
|
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: ["[email protected]", "[email protected]"]
|
|
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
|
|
|
|
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. To fix this, you need to escape the templates
|
|
using one of these methods:
|
|
|
|
1. Use YAML literal style (recommended):
|
|
headers:
|
|
- name: "Authorization"
|
|
value: |
|
|
Bearer {{.AccessToken}}
|
|
|
|
2. Use single quotes:
|
|
headers:
|
|
- name: "Authorization"
|
|
value: 'Bearer {{.AccessToken}}'
|
|
|
|
3. For inline double quotes, escape the braces:
|
|
headers:
|
|
- name: "Authorization"
|
|
value: "Bearer {{"{{.AccessToken}}"}}"
|
|
|
|
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
|