mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-06-05 22:44:17 +00:00
2d1b04c637
* Multiple fixes - refresh coordinator dedup + memory pressure wire - middleware sse consolidation + timer leak + claim cache - universal cache sync backfill + isDebug gate - lazy background task race - memory monitor stw cached + refresh() api * fix(auth): suppress OIDC redirects on non-navigation requests - [x] Add isNonNavigationRequest using Sec-Fetch-Mode and Accept headers - [x] Add comprehensive TestIsNonNavigationRequest - [x] Update ServeHTTP to 401 non-navigation and AJAX requests Fixes #129 * feat(config): add custom CA and insecure skip verify for OIDC TLS - [x] Add CACertPath, CACertPEM, InsecureSkipVerify to Config - [x] Implement loadCACertPool for CA bundle loading - [x] Update HTTPClientConfig with RootCAs and InsecureSkipVerify - [x] Apply CA pool and skip verify to pooled HTTP clients - [x] Enhance configKey to distinguish TLS configs - [x] Add comprehensive ca_cert_test.go Fixes #125 * feat(oidc): add custom CA certificate support for private OIDC providers - [x] Add caCertPath, caCertPEM, insecureSkipVerify config options - [x] Update traefik.yml with new OIDC client config fields - [x] Add configuration schema descriptions for new options - [x] Update README table and add Custom CA Certificates section * Fix the documentation. * test(redis): add oversized argument rejection test - [x] Add TestRedisConn_RejectOversizedArgumentBytes - [x] Import strings package * Dependencies cleanup
583 lines
14 KiB
Markdown
583 lines
14 KiB
Markdown
# OIDC Provider Configuration Guide
|
|
|
|
Configuration reference for each supported OIDC provider.
|
|
|
|
## Table of Contents
|
|
|
|
- [Provider Support Matrix](#provider-support-matrix)
|
|
- [Google](#google)
|
|
- [Microsoft Azure AD](#microsoft-azure-ad)
|
|
- [Auth0](#auth0)
|
|
- [Okta](#okta)
|
|
- [Keycloak](#keycloak)
|
|
- [AWS Cognito](#aws-cognito)
|
|
- [GitLab](#gitlab)
|
|
- [GitHub](#github)
|
|
- [Generic OIDC](#generic-oidc)
|
|
- [Automatic Scope Filtering](#automatic-scope-filtering)
|
|
|
|
---
|
|
|
|
## Provider Support Matrix
|
|
|
|
| Provider | OIDC Support | Refresh Tokens | Auto-Detection | ID Tokens |
|
|
|----------|-------------|----------------|----------------|-----------|
|
|
| Google | Full | Yes | `accounts.google.com` | Yes |
|
|
| Azure AD | Full | Yes | `login.microsoftonline.com`, `sts.windows.net` | Yes |
|
|
| Auth0 | Full | Yes | `*.auth0.com` | Yes |
|
|
| Okta | Full | Yes | `*.okta.com`, `*.oktapreview.com`, `*.okta-emea.com` | Yes |
|
|
| Keycloak | Full | Yes | host containing `keycloak`, or `/realms/` in path (matches both `/auth/realms/` legacy and `/realms/` modern) | Yes |
|
|
| AWS Cognito | Full | Yes | `cognito-idp.*.amazonaws.com` | Yes |
|
|
| GitLab | Full | Yes | `gitlab.com` | Yes |
|
|
| GitHub | OAuth 2.0 Only | No | `github.com` | No |
|
|
| Generic | Full | Yes | Any OIDC endpoint | Yes |
|
|
|
|
---
|
|
|
|
## Google
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
providerURL: "https://accounts.google.com"
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-google
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://accounts.google.com"
|
|
clientID: "your-id.apps.googleusercontent.com"
|
|
clientSecret: "your-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- email
|
|
- profile
|
|
allowedUserDomains:
|
|
- "your-gsuite-domain.com" # Optional: Workspace restriction
|
|
forceHttps: true
|
|
enablePkce: true
|
|
```
|
|
|
|
### Google-Specific Features
|
|
|
|
- **Automatic offline access**: Middleware adds `access_type=offline` and `prompt=consent`
|
|
- **Scope filtering**: Automatically removes unsupported `offline_access` scope
|
|
- **Workspace domains**: Restrict to specific Google Workspace domains via `hd` claim
|
|
|
|
### Google Cloud Console Setup
|
|
|
|
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
2. Create or select a project
|
|
3. Navigate to APIs & Services > Credentials
|
|
4. Create OAuth 2.0 Client ID (Web application)
|
|
5. Add authorized redirect URI: `https://your-domain.com/oauth2/callback`
|
|
6. Configure OAuth consent screen (must be "Published" for production)
|
|
|
|
---
|
|
|
|
## Microsoft Azure AD
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
# Single tenant
|
|
providerURL: "https://login.microsoftonline.com/{tenant-id}/v2.0"
|
|
|
|
# Multi-tenant
|
|
providerURL: "https://login.microsoftonline.com/common/v2.0"
|
|
```
|
|
|
|
### Basic Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-azure
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://login.microsoftonline.com/common/v2.0"
|
|
clientID: "your-azure-client-id"
|
|
clientSecret: "your-azure-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
- offline_access
|
|
allowedRolesAndGroups:
|
|
- "App.Users"
|
|
- "Admin.Group"
|
|
forceHttps: true
|
|
```
|
|
|
|
### With Application ID URI (API Access)
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-azure-api
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://login.microsoftonline.com/common/v2.0"
|
|
clientID: "your-azure-client-id"
|
|
clientSecret: "your-azure-client-secret"
|
|
audience: "api://your-azure-client-id" # Application ID URI
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
forceHttps: true
|
|
```
|
|
|
|
### Users Without Email
|
|
|
|
```yaml
|
|
userIdentifierClaim: sub # Options: sub, oid, upn, preferred_username
|
|
allowedUsers:
|
|
- "user-object-id-1"
|
|
- "user-object-id-2"
|
|
```
|
|
|
|
### Azure AD Setup
|
|
|
|
1. Go to [Azure Portal](https://portal.azure.com/)
|
|
2. Navigate to Azure Active Directory > App registrations
|
|
3. Create new registration
|
|
4. Add redirect URI: `https://your-domain.com/oauth2/callback`
|
|
5. Create client secret in Certificates & secrets
|
|
6. Configure Token Configuration for group claims
|
|
|
|
---
|
|
|
|
## Auth0
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
providerURL: "https://your-domain.auth0.com"
|
|
```
|
|
|
|
### Basic Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-auth0
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://your-domain.auth0.com"
|
|
clientID: "your-auth0-client-id"
|
|
clientSecret: "your-auth0-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
- offline_access
|
|
postLogoutRedirectUri: "https://your-app.com"
|
|
forceHttps: true
|
|
enablePkce: true
|
|
```
|
|
|
|
### With Custom API Audience
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-auth0-api
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://your-domain.auth0.com"
|
|
clientID: "your-auth0-client-id"
|
|
clientSecret: "your-auth0-client-secret"
|
|
audience: "https://api.your-domain.com" # API identifier
|
|
strictAudienceValidation: true
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
roleClaimName: "https://your-app.com/roles" # Namespaced claim
|
|
groupClaimName: "https://your-app.com/groups"
|
|
allowedRolesAndGroups:
|
|
- admin
|
|
- editor
|
|
```
|
|
|
|
### Auth0 Action for Custom Claims
|
|
|
|
```javascript
|
|
exports.onExecutePostLogin = async (event, api) => {
|
|
const namespace = 'https://your-app.com/';
|
|
if (event.authorization) {
|
|
api.idToken.setCustomClaim(namespace + 'roles', event.authorization.roles);
|
|
api.idToken.setCustomClaim('email', event.user.email);
|
|
}
|
|
};
|
|
```
|
|
|
|
### Auth0 Setup
|
|
|
|
1. Go to [Auth0 Dashboard](https://manage.auth0.com/)
|
|
2. Create Regular Web Application
|
|
3. Configure Allowed Callback URLs: `https://your-domain.com/oauth2/callback`
|
|
4. Configure Allowed Logout URLs: `https://your-domain.com/oauth2/logout`
|
|
5. Enable OIDC Conformant in Advanced Settings
|
|
6. Create API in APIs section for custom audiences
|
|
|
|
See [AUTH0_AUDIENCE_GUIDE.md](AUTH0_AUDIENCE_GUIDE.md) for detailed audience configuration.
|
|
|
|
---
|
|
|
|
## Okta
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
providerURL: "https://your-domain.okta.com"
|
|
# Or with custom authorization server:
|
|
providerURL: "https://your-domain.okta.com/oauth2/default"
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-okta
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://your-domain.okta.com"
|
|
clientID: "your-okta-client-id"
|
|
clientSecret: "your-okta-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
- groups
|
|
- offline_access
|
|
allowedRolesAndGroups:
|
|
- admin
|
|
- "Everyone"
|
|
forceHttps: true
|
|
enablePkce: true
|
|
```
|
|
|
|
### Okta Setup
|
|
|
|
1. Access Okta Admin Console
|
|
2. Go to Applications > Create App Integration
|
|
3. Select OIDC - OpenID Connect > Web Application
|
|
4. Configure Sign-in redirect URIs: `https://your-domain.com/oauth2/callback`
|
|
5. Configure Sign-out redirect URIs: `https://your-domain.com/oauth2/logout`
|
|
6. Enable Authorization Code and Refresh Token grant types
|
|
7. Configure Groups claim in authorization server
|
|
|
|
---
|
|
|
|
## Keycloak
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
providerURL: "https://keycloak.your-domain.com/realms/{realm-name}"
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-keycloak
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://keycloak.company.com/realms/your-realm"
|
|
clientID: "your-keycloak-client-id"
|
|
clientSecret: "your-keycloak-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
- roles
|
|
- groups
|
|
- offline_access
|
|
allowedRolesAndGroups:
|
|
- admin
|
|
- editor
|
|
forceHttps: true
|
|
enablePkce: true
|
|
```
|
|
|
|
### Internal Network Deployment
|
|
|
|
For private IP addresses (Docker networks, Kubernetes):
|
|
|
|
```yaml
|
|
providerURL: "https://192.168.1.100:8443/realms/your-realm"
|
|
allowPrivateIPAddresses: true # Required for private IPs
|
|
```
|
|
|
|
### Keycloak Client Setup
|
|
|
|
1. Access Keycloak Admin Console
|
|
2. Select your realm
|
|
3. Go to Clients > Create client
|
|
4. Set Client Protocol: openid-connect
|
|
5. Set Access Type: confidential
|
|
6. Add Valid Redirect URIs: `https://your-domain.com/oauth2/callback`
|
|
7. Generate client secret in Credentials tab
|
|
8. Configure mappers to add claims to ID Token:
|
|
- Email: User Property mapper with "Add to ID token" enabled
|
|
- Roles: User Client Role mapper with "Add to ID token" enabled
|
|
- Groups: Group Membership mapper with "Add to ID token" enabled
|
|
|
|
See [KEYCLOAK_SETUP_GUIDE.md](KEYCLOAK_SETUP_GUIDE.md) for detailed step-by-step setup instructions, mapper configuration, troubleshooting, and performance optimization.
|
|
|
|
---
|
|
|
|
## AWS Cognito
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
providerURL: "https://cognito-idp.{region}.amazonaws.com/{user-pool-id}"
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-cognito
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_ABCDEF123"
|
|
clientID: "your-cognito-client-id"
|
|
clientSecret: "your-cognito-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
- aws.cognito.signin.user.admin
|
|
allowedRolesAndGroups:
|
|
- admin
|
|
- users
|
|
forceHttps: true
|
|
```
|
|
|
|
### AWS Cognito Setup
|
|
|
|
1. Create Cognito User Pool
|
|
2. Create App Client with OIDC scopes
|
|
3. Configure App Client settings:
|
|
- Callback URLs: `https://your-domain.com/oauth2/callback`
|
|
- Sign out URLs: `https://your-domain.com/oauth2/logout`
|
|
- OAuth flows: Authorization code grant
|
|
4. Configure hosted UI domain (optional)
|
|
5. Set up groups for role-based access
|
|
|
|
---
|
|
|
|
## GitLab
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
# GitLab.com
|
|
providerURL: "https://gitlab.com"
|
|
|
|
# Self-hosted
|
|
providerURL: "https://gitlab.your-company.com"
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-gitlab
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://gitlab.com"
|
|
clientID: "your-gitlab-application-id"
|
|
clientSecret: "your-gitlab-application-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
# Note: GitLab doesn't require offline_access scope
|
|
# Refresh tokens are issued automatically with openid
|
|
allowedRolesAndGroups:
|
|
- developers
|
|
- maintainers
|
|
forceHttps: true
|
|
enablePkce: true
|
|
```
|
|
|
|
### GitLab Setup
|
|
|
|
1. Go to GitLab Settings > Applications
|
|
2. Create new application
|
|
3. Add scopes: `openid`, `profile`, `email`
|
|
4. Set redirect URI: `https://your-domain.com/oauth2/callback`
|
|
5. Save and note Application ID and Secret
|
|
|
|
---
|
|
|
|
## GitHub
|
|
|
|
### Provider URL
|
|
|
|
```yaml
|
|
providerURL: "https://github.com"
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oauth-github
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://github.com/login/oauth"
|
|
clientID: "your-github-client-id"
|
|
clientSecret: "your-github-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- user:email
|
|
- read:user
|
|
allowedUsers:
|
|
- "github-username"
|
|
forceHttps: true
|
|
```
|
|
|
|
### Limitations
|
|
|
|
- **OAuth 2.0 only** - Not OpenID Connect
|
|
- **No ID tokens** - Only access tokens for API calls
|
|
- **No refresh tokens** - Users must re-authenticate on expiry
|
|
- **No standard claims** - User info requires API calls
|
|
|
|
Use GitHub only for API access, not for user authentication with claims.
|
|
|
|
### GitHub Setup
|
|
|
|
1. Go to GitHub Settings > Developer settings > OAuth Apps
|
|
2. Create new OAuth App
|
|
3. Set Authorization callback URL: `https://your-domain.com/oauth2/callback`
|
|
4. Note Client ID and generate Client Secret
|
|
|
|
---
|
|
|
|
## Generic OIDC
|
|
|
|
For any OIDC-compliant provider not listed above.
|
|
|
|
### Configuration
|
|
|
|
```yaml
|
|
apiVersion: traefik.io/v1alpha1
|
|
kind: Middleware
|
|
metadata:
|
|
name: oidc-generic
|
|
spec:
|
|
plugin:
|
|
traefikoidc:
|
|
providerURL: "https://oidc.your-provider.com"
|
|
clientID: "your-client-id"
|
|
clientSecret: "your-client-secret"
|
|
callbackURL: "/oauth2/callback"
|
|
sessionEncryptionKey: "your-32-char-encryption-key-here"
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
forceHttps: true
|
|
enablePkce: true
|
|
```
|
|
|
|
### Requirements
|
|
|
|
- Provider must expose `.well-known/openid-configuration` endpoint
|
|
- Must support authorization code flow
|
|
- ID tokens must contain required claims (email, sub, etc.)
|
|
|
|
---
|
|
|
|
## Automatic Scope Filtering
|
|
|
|
The middleware automatically filters OAuth scopes based on the provider's declared capabilities.
|
|
|
|
### How It Works
|
|
|
|
1. Fetches provider's `.well-known/openid-configuration`
|
|
2. Extracts `scopes_supported` field
|
|
3. Filters requested scopes to only include supported ones
|
|
4. Falls back to all requested scopes if provider doesn't declare supported scopes
|
|
|
|
### Example: Self-Hosted GitLab
|
|
|
|
Self-hosted GitLab may reject `offline_access` scope:
|
|
|
|
```yaml
|
|
scopes:
|
|
- openid
|
|
- profile
|
|
- email
|
|
- offline_access # Will be automatically filtered out if unsupported
|
|
```
|
|
|
|
The middleware will:
|
|
1. Read GitLab's discovery document
|
|
2. Detect `offline_access` is NOT in `scopes_supported`
|
|
3. Filter it out automatically
|
|
4. Authentication succeeds
|
|
|
|
### Logging
|
|
|
|
```
|
|
INFO: ScopeFilter: Filtered unsupported scopes: [offline_access]
|
|
DEBUG: ScopeFilter: Final filtered scopes: [openid profile email]
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
If a provider rejects scopes even after filtering:
|
|
1. Check the provider's discovery document: `curl https://provider/.well-known/openid-configuration`
|
|
2. Use `overrideScopes: true` with only supported scopes
|
|
3. Review middleware debug logs for filtering decisions
|