Skip to content

alliumm/oidc-forward-auth-middleware

 
 

Repository files navigation

OIDC ForwardAuth middleware (for traefik)

GitHub tag License Rust Report Card

This container acts as a ForwardAuth middleware for the traefik ingress controller that provides OpenID Connect (OIDC) authorization.


Features

  • Blazing fast ⚡️ and written in Rust ⚙️
  • Secure implementation 🔐 with PKCE, CSRF protection, and SameSite cookies
  • Integration with traefik ingress controller
  • Easy to deploy to a Kubernetes environment via Helm or to use it with Docker Compose
  • Simple configuration via environment variables or Helm values
  • Optional server-side session store with Redis/Valkey for improved token management

New features in version 4

  • Session Store: Optional server-side session storage using Redis/Valkey. This is essential for OIDC providers that use single-use refresh tokens (like Kanidm) to prevent race conditions when multiple concurrent requests attempt to refresh tokens.
  • Distributed locking: When session store is enabled, token refresh operations use distributed locks to ensure only one request refreshes the token at a time.

New features in version 3

  • Added the HTTP header X-Forwarded-User containing the jwt user sub. Your backend can directly consume that header to get the user id without the need to encrypt or validate jwt tokens.
  • Helm Chart: Added support for Traefik V2 and V3 middleware CRDs

Security

  • PKCE (Proof Key for Code Exchange) for secure authorization code flow
  • CSRF protection via state parameter with cryptographic nonce
  • HttpOnly & Secure cookies to prevent XSS attacks
  • SameSite=Lax cookies for additional CSRF protection
  • Automatic token expiry based on JWT exp claim
  • Redirect loop prevention on failed authentication callbacks

Getting started

Getting started with Kubernetes / Helm

Let's say you have a service called app.example.com you would like to protect with the OIDC middleware. Your OIDC provider in this example is id.example.com.

First, install the oidc-forward-auth-middleware Helm chart:

helm install oci://ghcr.io/espresso-lab/helm-charts/oidc-forward-auth-middleware

The Helm values could look like the following:

# Example helm values of oidc-forward-auth-middleware

config:
  logLevel: info # debug, info, warn, error

oidcProviders:
  - ingressHostname: app.example.com # Traefik ingress hostname you would like to protect
    issuerUrl: https://id.example.com/oauth/app1
    clientId: app1
    clientSecret: mysecretpassword
    scopes: ["email", "profile"]
    # existingSecret: oidc-config # Provide a secret in the same namespace with fields clientId, clientSecret
    audience: ["app1"]

Enabling Session Store (Recommended for Kanidm and similar providers)

If your OIDC provider uses single-use refresh tokens (e.g., Kanidm), enable the session store to prevent race conditions:

# Enable built-in Valkey instance
sessionStore:
  enabled: true

# Or use an external Redis/Valkey instance
sessionStore:
  enabled: true
  externalUrl: "redis://your-redis-host:6379"

Last, enable it in the ingress controller of the service app.example.com you would like to protect:

# Example helm values of service app.example.com
ingress:
  enabled: true
  hosts:
    - app.example.com
  ingressClassName: traefik
  annotations:
    # Enable middleware
    traefik.ingress.kubernetes.io/router.middlewares: kube-system-oidc-forward-auth-middleware@kubernetescrd

Getting started with Docker Compose

For the latest example have a look at the docker-compose.yml file.

Architecture

OIDC ForwardAuth Middleware Architecture

Configuration

Environment variables

General setting

Environment variable Type Description
RUST_LOG String info, debug, error, warning
BIND_ADDRESS String Default: 0.0.0.0:3000. The network address to bind to.
DISABLE_ENHANCED_SECURITY Boolean Default: false. Sets various security HTTP headers and redirects http requests to https.
REDIS_URL String Optional. Redis/Valkey connection URL for session store. Example: redis://localhost:6379

Per OIDC provider

Use OIDC_PROVIDER_0_* for the first provider, OIDC_PROVIDER_1_* for the second one and so on.

Environment variable Type Description Example
OIDC_PROVIDER_0_HOSTNAME String Name of the hostname (traefik ingress host) app.example.com
OIDC_PROVIDER_0_ISSUER_URL String OIDC issuer url https://id.example.com/oauth2/openid/app
OIDC_PROVIDER_0_CLIENT_ID String OIDC client id my-app-client
OIDC_PROVIDER_0_CLIENT_SECRET String OIDC client secret super-secret-password
OIDC_PROVIDER_0_SCOPES String OIDC scopes (openid, email, ...) openid,email,profile
OIDC_PROVIDER_0_AUDIENCE String OIDC audience my-app-client

Cookies

The middleware sets the following cookies:

Without session store (default):

Cookie Purpose Expiry
x_oidc_access_token JWT access token Based on JWT exp claim
x_oidc_refresh_token Refresh token for silent renewal Session
x_oidc_csrf_{nonce} CSRF protection during auth flow 1 hour
x_oidc_pkce_{nonce} PKCE verifier during auth flow 1 hour

With session store enabled:

Cookie Purpose Expiry
x_oidc_session Session ID (tokens stored server-side) 24 hours
x_oidc_csrf_{nonce} CSRF protection during auth flow 1 hour
x_oidc_pkce_{nonce} PKCE verifier during auth flow 1 hour

License

Released under MIT by @espresso-lab.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 93.3%
  • Go Template 3.9%
  • Dockerfile 2.8%