OAuth2 Proxy¶
Overview¶
OAuth2 Proxy provides centralized authentication for AKKO services that lack native OIDC support. It acts as an authentication gateway between Traefik and backend services, validating user sessions against Keycloak before allowing access. This eliminates the need to implement OAuth2/OIDC in every service.
Architecture¶
Browser ──→ Traefik (:443)
│
│ forward-auth middleware
▼
OAuth2 Proxy (:4180)
│
│ validates session
▼
Keycloak
(OIDC provider)
│
│ session valid → allow
▼
Backend Service
(Dashboards, MLflow, LiteLLM, Cockpit)
Traefik's forward-auth middleware sends every incoming request to OAuth2 Proxy for validation. If the user has a valid session cookie, the request is forwarded to the backend. If not, the user is redirected to Keycloak's login page.
Ports¶
| Port | Purpose | Exposed |
|---|---|---|
| 4180 | HTTP — authentication proxy endpoint | Internal only (accessed by Traefik middleware) |
Not Directly Accessible
Users never access OAuth2 Proxy directly. Traefik routes authentication requests to it transparently via the forward-auth middleware.
Protected Services¶
| Service | Why OAuth2 Proxy? |
|---|---|
| Dashboards | Dashboards supports OAuth natively, but OAuth2 Proxy provides unified session management |
| MLflow | No built-in authentication — fully open by default |
| LiteLLM | API gateway with basic auth only — needs OIDC protection |
| Cockpit | Static HTML/JS portal — no backend auth capability |
Services with native Keycloak OIDC support (JupyterHub, Superset, Airflow, Keycloak itself) handle authentication directly and do not use OAuth2 Proxy.
Configuration¶
Keycloak OIDC Provider¶
OAuth2 Proxy is configured to use Keycloak as the OIDC identity provider:
provider: keycloak-oidc
oidc-issuer-url: https://identity.akko.local/realms/akko
client-id: akko-oauth2-proxy
client-secret: ${OAUTH2_PROXY_CLIENT_SECRET}
Cookie Settings¶
cookie-name: _akko_oauth2
cookie-secret: ${OAUTH2_PROXY_COOKIE_SECRET} # 32-byte random base64
cookie-domain: .akko.local # shared across all subdomains
cookie-secure: true
cookie-samesite: lax
Cookie Domain Must Match
The cookie-domain must be set to the base domain shared by all services
(.akko.local in k3d). If services use different domains, the session
cookie will not be shared and users will face repeated login prompts.
Upstream and Redirect¶
upstream: static://200 # return 200 for valid sessions
redirect-url: https://akko.local/oauth2/callback
email-domain: "*" # allow all email domains
The static://200 upstream means OAuth2 Proxy does not proxy traffic itself —
it only validates the session and returns headers to Traefik.
Traefik Integration¶
The forward-auth middleware is defined as a Traefik CRD:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: oauth2-proxy-forward-auth
spec:
forwardAuth:
address: http://akko-oauth2-proxy:4180/oauth2/auth
trustForwardHeader: true
authResponseHeaders:
- X-Auth-Request-User
- X-Auth-Request-Email
- X-Auth-Request-Groups
Services that need protection add this annotation to their Ingress:
Helm Chart¶
OAuth2 Proxy is deployed via the akko-oauth2-proxy custom sub-chart:
helm/akko/charts/akko-oauth2-proxy/
├── Chart.yaml
├── values.yaml
└── templates/
├── deployment.yaml
├── service.yaml
├── secret.yaml
├── middleware.yaml # Traefik CRD
└── ingress.yaml # for /oauth2/callback
Key Values¶
akko-oauth2-proxy:
image:
repository: quay.io/oauth2-proxy/oauth2-proxy
tag: "7.7.1"
provider: keycloak-oidc
cookie:
domain: .akko.local
ingress:
enabled: true
hostname: akko.local
path: /oauth2
Health Check¶
Returns OK when the proxy is ready.
Troubleshooting¶
Common Issues
- Infinite redirect loop: The most common cause is a mismatch between
the
redirect-urland the Keycloak client's valid redirect URIs. Verify in Keycloak admin (Clients >akko-oauth2-proxy> Valid Redirect URIs) thathttps://akko.local/oauth2/callbackis listed. Also check the cookie domain. - 403 Forbidden after login: OAuth2 Proxy may reject the user if
email-domainis too restrictive or the Keycloak token does not include the expected claims. Check OAuth2 Proxy logs withkubectl logs deploy/akko-oauth2-proxyfor details. - Session lost between services: All services must share the same
cookie-domain(.akko.local). If one service uses a different domain, the cookie is not sent and the user appears unauthenticated.