Files
traefikoidc/docs/DCR.md
lukaszraczylo 2d1b04c637 review fixes apr 2026 (#130)
* 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
2026-04-19 10:12:00 +01:00

4.5 KiB

Dynamic Client Registration (RFC 7591)

The middleware can register itself with an OIDC provider at startup instead of using a pre-provisioned clientID / clientSecret. Useful for multi-tenant deployments, self-service integrations, and ephemeral environments.

How it works

  1. Middleware reads registration_endpoint from .well-known/openid-configuration.
  2. If clientID is empty, it POSTs clientMetadata to the registration endpoint.
  3. Returned client_id / client_secret are cached, optionally persisted.
  4. Subsequent requests use the registered credentials.

For multi-replica deployments, set storageBackend: redis so all replicas share one client and avoid registration races.

Configuration

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: oidc-dcr
  namespace: traefik
spec:
  plugin:
    traefikoidc:
      providerURL: https://your-oidc-provider.com
      sessionEncryptionKey: your-secure-encryption-key-min-32-chars
      callbackURL: /oauth2/callback
      dynamicClientRegistration:
        enabled: true
        persistCredentials: true
        storageBackend: redis        # file | redis | auto
        initialAccessToken: ""        # optional, for protected endpoints
        registrationEndpoint: ""      # optional, override discovery
        credentialsFile: /tmp/oidc-client-credentials.json
        redisKeyPrefix: "dcr:creds:"
        clientMetadata:
          redirect_uris:
            - https://app.example.com/oauth2/callback
          client_name: My Application
          application_type: web
          grant_types: [authorization_code, refresh_token]
          response_types: [code]
          token_endpoint_auth_method: client_secret_basic
          contacts: [admin@example.com]

Parameters

Parameter Default Description
enabled false Enable DCR.
persistCredentials false Save returned credentials for reuse across restarts.
storageBackend auto file, redis, or auto (Redis if available, else file).
credentialsFile /tmp/oidc-client-credentials.json Path for file-backed storage. Mode 0600.
redisKeyPrefix (none — set explicitly) Key prefix for Redis-backed storage. The code does not inject a default; if unset, keys have no prefix. dcr:creds: is a sensible convention.
registrationEndpoint discovered Override the discovered endpoint.
initialAccessToken none Bearer token for protected registration endpoints.
clientMetadata.redirect_uris required Callback URIs for the OAuth flow.
clientMetadata.client_name none Human-readable client name.
clientMetadata.application_type web web or native.
clientMetadata.grant_types [authorization_code, refresh_token] OAuth grant types.
clientMetadata.response_types [code] OAuth response types.
clientMetadata.token_endpoint_auth_method client_secret_basic client_secret_basic, client_secret_post, or none.
clientMetadata.scope none Space-separated scopes.
clientMetadata.contacts none Admin email addresses.
clientMetadata.logo_uri none Logo URL for consent screens.
clientMetadata.client_uri none Client homepage URL.
clientMetadata.policy_uri none Privacy policy URL.
clientMetadata.tos_uri none Terms of service URL.

Provider support

The middleware does not gate DCR by provider — if the provider exposes a registration_endpoint in its discovery document (or you set registrationEndpoint explicitly), DCR will attempt registration. The table below is informational guidance based on each provider's published support.

Provider DCR Notes
Keycloak Yes Enable in realm settings.
Auth0 Yes Requires Management API token.
Okta Yes Enable Dynamic Client Registration in admin console.
Azure AD Limited Use App Registration API instead.
Google No Manual registration required.
AWS Cognito No Manual registration required.

Security notes

  • Registration endpoints must be HTTPS (loopback excepted for local dev).
  • Use initialAccessToken in production to gate registration.
  • File-backed credentials use 0600; protect the mount path.
  • The plugin marks credentials invalid when within ~5 min of client_secret_expires_at but does not automatically re-register. If your provider sets a non-zero expiry, schedule manual rotation (delete the credentials file or Redis entry, restart) before that time.