Files
traefikoidc/docs/AUTH0_AUDIENCE_GUIDE.md
T
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

11 KiB

Auth0 Audience Validation Guide

Overview

This guide explains how to configure audience validation for Auth0 and other OIDC providers that support custom API audiences. It covers three common Auth0 scenarios and how to configure the middleware for maximum security.

Table of Contents

  1. Understanding Audiences
  2. The Three Auth0 Scenarios
  3. Configuration Options
  4. Security Recommendations
  5. Troubleshooting

Understanding Audiences

What is an Audience?

The audience (aud) claim in a JWT identifies the intended recipient of the token. Per OAuth 2.0 and OIDC specifications:

  • ID Tokens: MUST have aud = client_id (per OIDC Core 1.0 spec)
  • Access Tokens: Can have custom audiences (e.g., API identifiers)

Why Does This Matter?

Audience validation rejects access tokens whose aud claim does not match the expected audience, blocking the trivial form of token confusion where a token issued for API A is presented to API B. (Defence in depth — pair with short-lived tokens, rotation, and per-API client credentials.)


The Three Auth0 Scenarios

Configuration:

audience: "https://my-api.example.com"  # Your API identifier from Auth0

What Happens:

  1. Authorization request includes audience parameter
  2. Auth0 issues:
    • ID Token: aud = client_id
    • Access Token: aud = ["https://issuer/userinfo", "https://my-api.example.com"]
  3. Middleware validates:
    • ID tokens against client_id
    • Access tokens against custom audience

Result: Fully secure, OIDC compliant


Scenario 2: Default Audience (No Custom API) ⚠️ USE WITH CAUTION

Configuration:

# audience not specified (defaults to client_id)

What Happens:

  1. Authorization request WITHOUT audience parameter
  2. Auth0 issues:
    • ID Token: aud = client_id
    • Access Token: aud = ["https://issuer/userinfo", "default_api"] (no client_id)
  3. Access token validation fails (audience mismatch)
  4. Middleware falls back to ID token validation

Security Warning:

⚠️⚠️⚠️  SECURITY WARNING: Falling back to ID token validation despite access token audience mismatch!
⚠️  This could allow tokens intended for different APIs to grant access
⚠️  Set strictAudienceValidation=true to enforce proper audience validation
⚠️  See: https://github.com/lukaszraczylo/traefikoidc/issues/74

Recommended Fix:

strictAudienceValidation: true  # Reject sessions with audience mismatch

Result:

  • Default: ⚠️ Works but logs security warnings
  • With strict mode: Secure (rejects mismatched tokens)

Scenario 3: Opaque Access Tokens SUPPORTED

Configuration:

allowOpaqueTokens: true              # Enable opaque token support
requireTokenIntrospection: true      # Require introspection (recommended)

What Happens:

  1. Auth0 issues opaque (non-JWT) access token
  2. Middleware detects opaque token (not 3 parts separated by dots)
  3. Uses OAuth 2.0 Token Introspection (RFC 7662) to validate
  4. Falls back to ID token if introspection unavailable (unless requireTokenIntrospection=true)

Requirements:

  • Provider must support introspection_endpoint in OIDC discovery
  • Client must have introspection permissions

Result: Secure with introspection, ⚠️ risky without


Configuration Options

Audience Settings

Option Type Default Description
audience string client_id Expected audience for access tokens

Example:

# .traefik.yml
http:
  middlewares:
    oidc-auth:
      plugin:
        traefikoidc:
          audience: "https://my-api.example.com"

Security Mode Settings

strictAudienceValidation

Type: boolean Default: false Recommended: true for production

What it does:

  • When true: On audience mismatch, the middleware does not silently fall back to ID-token validation. It tries to refresh the access token first; if no refresh token is present (or refresh fails), the user is re-authenticated.
  • When false: Logs warnings and falls back to ID-token validation (backward compatible).

Example:

strictAudienceValidation: true

When to use:

  • Always use in production environments
  • When you have custom API audiences configured in Auth0
  • ⚠️ May break existing deployments relying on Scenario 2 behavior

allowOpaqueTokens

Type: boolean Default: false

What it does:

  • When true: Accepts opaque (non-JWT) access tokens
  • When false: Only accepts JWT access tokens

Example:

allowOpaqueTokens: true

When to use:

  • When Auth0 issues opaque tokens (no default API configured)
  • When using Auth0 Management API tokens
  • ⚠️ Requires introspection endpoint for security

requireTokenIntrospection

Type: boolean Default: false Recommended: true when allowOpaqueTokens=true

What it does:

  • When true: Rejects opaque tokens if introspection fails or endpoint unavailable
  • When false: Falls back to ID token validation for opaque tokens

Example:

allowOpaqueTokens: true
requireTokenIntrospection: true

When to use:

  • Always use when allowOpaqueTokens=true for maximum security
  • ⚠️ Requires provider to expose introspection endpoint

Security Recommendations

For APIs with custom audiences (Scenario 1):

audience: "https://my-api.example.com"
strictAudienceValidation: true
allowOpaqueTokens: false

For default Auth0 setup (Scenario 2):

# Don't set audience (defaults to client_id)
strictAudienceValidation: true  # Enforce proper configuration

For opaque tokens (Scenario 3):

allowOpaqueTokens: true
requireTokenIntrospection: true
strictAudienceValidation: true

Security Best Practices

  1. Always set strictAudienceValidation: true in production
  2. Configure custom API audiences in Auth0 dashboard
  3. Use requireTokenIntrospection: true if accepting opaque tokens
  4. Monitor logs for security warnings
  5. Don't rely on Scenario 2 fallback behavior

Troubleshooting

"Access token validation failed due to audience mismatch"

Symptom:

⚠️  SCENARIO 2 DETECTED: Access token validation failed due to audience mismatch

Cause: Access token audience doesn't match configured audience

Solutions:

  1. Configure correct audience:

    audience: "https://your-api-identifier"  # From Auth0 API settings
    
  2. Update Auth0 authorization request:

    • Ensure audience parameter is included in authorize URL
    • Middleware automatically adds this when audience != client_id
  3. Accept the behavior (not recommended):

    strictAudienceValidation: false  # Logs warnings but allows
    

"Opaque token detected but allowOpaqueTokens=false"

Symptom:

⚠️  Opaque access token detected but allowOpaqueTokens=false

Cause: Auth0 issued non-JWT access token but middleware not configured to accept them

Solutions:

  1. Enable opaque tokens:

    allowOpaqueTokens: true
    requireTokenIntrospection: true
    
  2. Configure Auth0 to issue JWT access tokens:

    • Create an API in Auth0 dashboard
    • Set API identifier as audience in configuration

"Introspection endpoint not available"

Symptom:

⚠️  Opaque tokens enabled but no introspection endpoint available from provider

Cause: Auth0 provider metadata doesn't include introspection_endpoint

Solutions:

  1. Check provider discovery:

    curl https://YOUR_DOMAIN/.well-known/openid-configuration
    

    Look for introspection_endpoint

  2. Disable required introspection (less secure):

    allowOpaqueTokens: true
    requireTokenIntrospection: false  # Falls back to ID token
    
  3. Use JWT access tokens instead (recommended)


"Token introspection required but endpoint not available"

Symptom:

❌ SECURITY: Opaque token rejected (introspection required but failed)

Cause: requireTokenIntrospection=true but provider doesn't support it

Solutions:

  1. Disable required introspection:

    requireTokenIntrospection: false
    
  2. Configure Auth0 to issue JWT tokens (better solution)


Advanced Topics

Token Type Detection

The middleware uses a sophisticated 6-step detection algorithm:

  1. RFC 9068 typ header: at+jwt → Access Token
  2. Explicit type claims: token_use, token_type
  3. scope claim: Present → Access Token
  4. nonce claim: Present → ID Token (OIDC spec)
  5. Audience check: aud == client_id only → ID Token
  6. Default: Access Token

OAuth 2.0 Token Introspection (RFC 7662)

When opaque tokens are detected:

  1. Middleware calls provider's introspection_endpoint
  2. Authenticates using client credentials
  3. Receives response with active status and claims
  4. Caches result for 5 minutes (configurable via TTL)
  5. Validates expiration, not-before, and audience if present

Cache behavior:

  • Cache key: Token hash
  • TTL: 5 minutes; if the token's exp is sooner, the cache entry expires at exp instead. Tokens without exp use the flat 5-minute TTL.
  • Reduces introspection requests for frequently used tokens


Migration Guide

From Previous Versions

If you're upgrading from a version without these features:

  1. No action required for default behavior - backward compatible

  2. Recommended: Enable strict mode gradually

    # Step 1: Enable and monitor logs
    strictAudienceValidation: false  # Default
    
    # Step 2: After confirming no warnings, enable
    strictAudienceValidation: true
    
  3. For opaque tokens: Enable explicitly

    allowOpaqueTokens: true
    requireTokenIntrospection: true
    

Testing Your Configuration

  1. Check logs for warnings:

    # Look for Scenario 2 warnings
    grep "SCENARIO 2 DETECTED" /var/log/traefik.log
    
    # Look for opaque token warnings
    grep "Opaque" /var/log/traefik.log
    
  2. Test with curl:

    # Get token from Auth0
    ACCESS_TOKEN="your_access_token"
    
    # Test request
    curl -H "Authorization: Bearer $ACCESS_TOKEN" \
         https://your-app.example.com/api
    
  3. Monitor for security warnings in production logs


Support

For issues or questions:


Last Updated: 2025-01-09 Version: 0.7.8+