From a360cb3875c7cfff13d5c04822eff9192236e460 Mon Sep 17 00:00:00 2001 From: Jan Larwig Date: Fri, 16 Jan 2026 09:48:37 +0100 Subject: [PATCH] docs: backport integrations split to v7.14.x & v7.13.x Signed-off-by: Jan Larwig --- .../configuration/integration.md | 310 ------------------ .../configuration/integrations/caddy.md | 63 ++++ .../configuration/integrations/headlamp.md | 105 ++++++ .../configuration/integrations/index.md | 41 +++ .../integrations/kubernetes-dashboard.md | 289 ++++++++++++++++ .../configuration/integrations/nginx.md | 107 ++++++ .../configuration/integrations/traefik.md | 184 +++++++++++ .../version-7.13.x/features/endpoints.md | 2 +- .../configuration/integration.md | 310 ------------------ .../configuration/integrations/caddy.md | 63 ++++ .../configuration/integrations/headlamp.md | 105 ++++++ .../configuration/integrations/index.md | 41 +++ .../integrations/kubernetes-dashboard.md | 289 ++++++++++++++++ .../configuration/integrations/nginx.md | 107 ++++++ .../configuration/integrations/traefik.md | 184 +++++++++++ .../version-7.14.x/configuration/overview.md | 4 +- .../version-7.14.x/features/endpoints.md | 2 +- .../version-7.13.x-sidebars.json | 16 +- .../version-7.14.x-sidebars.json | 16 +- 19 files changed, 1612 insertions(+), 626 deletions(-) delete mode 100644 docs/versioned_docs/version-7.13.x/configuration/integration.md create mode 100644 docs/versioned_docs/version-7.13.x/configuration/integrations/caddy.md create mode 100644 docs/versioned_docs/version-7.13.x/configuration/integrations/headlamp.md create mode 100644 docs/versioned_docs/version-7.13.x/configuration/integrations/index.md create mode 100644 docs/versioned_docs/version-7.13.x/configuration/integrations/kubernetes-dashboard.md create mode 100644 docs/versioned_docs/version-7.13.x/configuration/integrations/nginx.md create mode 100644 docs/versioned_docs/version-7.13.x/configuration/integrations/traefik.md delete mode 100644 docs/versioned_docs/version-7.14.x/configuration/integration.md create mode 100644 docs/versioned_docs/version-7.14.x/configuration/integrations/caddy.md create mode 100644 docs/versioned_docs/version-7.14.x/configuration/integrations/headlamp.md create mode 100644 docs/versioned_docs/version-7.14.x/configuration/integrations/index.md create mode 100644 docs/versioned_docs/version-7.14.x/configuration/integrations/kubernetes-dashboard.md create mode 100644 docs/versioned_docs/version-7.14.x/configuration/integrations/nginx.md create mode 100644 docs/versioned_docs/version-7.14.x/configuration/integrations/traefik.md diff --git a/docs/versioned_docs/version-7.13.x/configuration/integration.md b/docs/versioned_docs/version-7.13.x/configuration/integration.md deleted file mode 100644 index c57cfa6b..00000000 --- a/docs/versioned_docs/version-7.13.x/configuration/integration.md +++ /dev/null @@ -1,310 +0,0 @@ ---- -id: integration -title: Integration ---- - -## Configuring for use with the Nginx `auth_request` directive - -**This option requires `--reverse-proxy` option to be set.** - -The [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) allows Nginx to authenticate requests via the oauth2-proxy's `/auth` endpoint, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the request through. For example: - -```nginx -server { - listen 443 ssl; - server_name ...; - include ssl/ssl.conf; - - location /oauth2/ { - proxy_pass http://127.0.0.1:4180; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Auth-Request-Redirect $request_uri; - # or, if you are handling multiple domains: - # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; - } - location = /oauth2/auth { - proxy_pass http://127.0.0.1:4180; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Uri $request_uri; - # nginx auth_request includes headers but not body - proxy_set_header Content-Length ""; - proxy_pass_request_body off; - } - - location / { - auth_request /oauth2/auth; - error_page 401 =403 /oauth2/sign_in; - - # pass information via X-User and X-Email headers to backend, - # requires running with --set-xauthrequest flag - auth_request_set $user $upstream_http_x_auth_request_user; - auth_request_set $email $upstream_http_x_auth_request_email; - proxy_set_header X-User $user; - proxy_set_header X-Email $email; - - # if you enabled --pass-access-token, this will pass the token to the backend - auth_request_set $token $upstream_http_x_auth_request_access_token; - proxy_set_header X-Access-Token $token; - - # if you enabled --cookie-refresh, this is needed for it to work with auth_request - auth_request_set $auth_cookie $upstream_http_set_cookie; - add_header Set-Cookie $auth_cookie; - - # When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb - # limit and so the OAuth2 Proxy splits these into multiple parts. - # Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response, - # so if your cookies are larger than 4kb, you will need to extract additional cookies manually. - auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1; - - # Extract the Cookie attributes from the first Set-Cookie header and append them - # to the second part ($upstream_cookie_* variables only contain the raw cookie content) - if ($auth_cookie ~* "(; .*)") { - set $auth_cookie_name_0 $auth_cookie; - set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1"; - } - - # Send both Set-Cookie headers now if there was a second part - if ($auth_cookie_name_upstream_1) { - add_header Set-Cookie $auth_cookie_name_0; - add_header Set-Cookie $auth_cookie_name_1; - } - - proxy_pass http://backend/; - # or "root /path/to/site;" or "fastcgi_pass ..." etc - } -} -``` - -When you use ingress-nginx in Kubernetes, you can configure the same behavior with the following annotations on your Ingress resource: - -```yaml -nginx.ingress.kubernetes.io/auth-url: "https:///oauth2/auth" -nginx.ingress.kubernetes.io/auth-signin: "https:///oauth2/start?rd=$escaped_request_uri" -``` - -This minimal configuration works for standard authentication flows. Lua/cookie handling is only needed for advanced scenarios (e.g., multi-part cookies, custom session logic). See the official ingress-nginx example: https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/. - -It is recommended to use `--session-store-type=redis` when expecting large sessions/OIDC tokens (_e.g._ with MS Azure). - -You have to substitute *name* with the actual cookie name you configured via --cookie-name parameter. If you don't set a custom cookie name the variable should be "$upstream_cookie__oauth2_proxy_1" instead of "$upstream_cookie_name_1" and the new cookie-name should be "_oauth2_proxy_1=" instead of "name_1=". - -## Configuring for use with the Traefik (v2) `ForwardAuth` middleware - -**This option requires `--reverse-proxy` option to be set.** - -### ForwardAuth with 401 errors middleware - -The [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) allows Traefik to authenticate requests via the oauth2-proxy's `/oauth2/auth` endpoint on every request, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the whole request through. For example, on Dynamic File (YAML) Configuration: - -```yaml -http: - routers: - a-service: - rule: "Host(`a-service.example.com`)" - service: a-service-backend - middlewares: - - oauth-errors - - oauth-auth - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - oauth: - rule: "Host(`a-service.example.com`, `oauth.example.com`) && PathPrefix(`/oauth2/`)" - middlewares: - - auth-headers - service: oauth-backend - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - - services: - a-service-backend: - loadBalancer: - servers: - - url: http://172.16.0.2:7555 - oauth-backend: - loadBalancer: - servers: - - url: http://172.16.0.1:4180 - - middlewares: - auth-headers: - headers: - sslRedirect: true - stsSeconds: 315360000 - browserXssFilter: true - contentTypeNosniff: true - forceSTSHeader: true - sslHost: example.com - stsIncludeSubdomains: true - stsPreload: true - frameDeny: true - oauth-auth: - forwardAuth: - address: https://oauth.example.com/oauth2/auth - trustForwardHeader: true - oauth-errors: - errors: - status: - - "401-403" - service: oauth-backend - query: "/oauth2/sign_in?rd={url}" -``` - -### ForwardAuth with static upstreams configuration - -Redirect to sign_in functionality provided without the use of `errors` middleware with [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) pointing to oauth2-proxy service's `/` endpoint - -**Following options need to be set on `oauth2-proxy`:** -- `--upstream=static://202`: Configures a static response for authenticated sessions -- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly - -```yaml -http: - routers: - a-service-route-1: - rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/`)" - service: a-service-backend - middlewares: - - oauth-auth-redirect # redirects all unauthenticated to oauth2 signin - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - a-service-route-2: - rule: "Host(`a-service.example.com`) && PathPrefix(`/no-auto-redirect`)" - service: a-service-backend - middlewares: - - oauth-auth-wo-redirect # unauthenticated session will return a 401 - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - services-oauth2-route: - rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/oauth2/`)" - middlewares: - - auth-headers - service: oauth-backend - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - oauth2-proxy-route: - rule: "Host(`oauth.example.com`) && PathPrefix(`/`)" - middlewares: - - auth-headers - service: oauth-backend - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - - services: - a-service-backend: - loadBalancer: - servers: - - url: http://172.16.0.2:7555 - b-service-backend: - loadBalancer: - servers: - - url: http://172.16.0.3:7555 - oauth-backend: - loadBalancer: - servers: - - url: http://172.16.0.1:4180 - - middlewares: - auth-headers: - headers: - sslRedirect: true - stsSeconds: 315360000 - browserXssFilter: true - contentTypeNosniff: true - forceSTSHeader: true - sslHost: example.com - stsIncludeSubdomains: true - stsPreload: true - frameDeny: true - oauth-auth-redirect: - forwardAuth: - address: https://oauth.example.com/ - trustForwardHeader: true - authResponseHeaders: - - X-Auth-Request-Access-Token - - Authorization - oauth-auth-wo-redirect: - forwardAuth: - address: https://oauth.example.com/oauth2/auth - trustForwardHeader: true - authResponseHeaders: - - X-Auth-Request-Access-Token - - Authorization -``` - -## Configuring for use with the Caddy (v2) `forward_auth` directive - -The [Caddy `forward_auth` directive](https://caddyserver.com/docs/caddyfile/directives/forward_auth) allows Caddy to authenticate requests via the `oauth2-proxy`'s `/auth`. - -This example is for a simple reverse proxy setup where the `/oauth2/` path is kept under the same domain and failed auth requests (401 status returned) will be caught and redirected to the `sign_in` endpoint. - -**Following options need to be set on `oauth2-proxy`:** -- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly - -```nginx title="Caddyfile" -example.com { - # Requests to /oauth2/* are proxied to oauth2-proxy without authentication. - # You can't use `reverse_proxy /oauth2/* oauth2-proxy.internal:4180` here because the reverse_proxy directive has lower precedence than the handle directive. - handle /oauth2/* { - reverse_proxy oauth2-proxy.internal:4180 { - # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. - # The reverse_proxy directive automatically sets X-Forwarded-{For,Proto,Host} headers. - header_up X-Real-IP {remote_host} - header_up X-Forwarded-Uri {uri} - } - } - - # Requests to other paths are first processed by oauth2-proxy for authentication. - handle { - forward_auth oauth2-proxy.internal:4180 { - uri /oauth2/auth - - # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. - # The forward_auth directive automatically sets the X-Forwarded-{For,Proto,Host,Method,Uri} headers. - header_up X-Real-IP {remote_host} - - # If needed, you can copy headers from the oauth2-proxy response to the request sent to the upstream. - # Make sure to configure the --set-xauthrequest flag to enable this feature. - #copy_headers X-Auth-Request-User X-Auth-Request-Email - - # If oauth2-proxy returns a 401 status, redirect the client to the sign-in page. - @error status 401 - handle_response @error { - redir * /oauth2/sign_in?rd={scheme}://{host}{uri} - } - } - - # If oauth2-proxy returns a 2xx status, the request is then proxied to the upstream. - reverse_proxy upstream.internal:3000 - } -} -``` - -:::note -If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. -::: diff --git a/docs/versioned_docs/version-7.13.x/configuration/integrations/caddy.md b/docs/versioned_docs/version-7.13.x/configuration/integrations/caddy.md new file mode 100644 index 00000000..1805e559 --- /dev/null +++ b/docs/versioned_docs/version-7.13.x/configuration/integrations/caddy.md @@ -0,0 +1,63 @@ +--- +id: caddy +title: Caddy +--- + +Integrate OAuth2 Proxy with Caddy v2 using the `forward_auth` directive. + +**Key features:** +- Simple forward_auth setup +- Automatic header handling +- Custom error handling and redirects + +## Configuring for use with the Caddy (v2) `forward_auth` directive + +The [Caddy `forward_auth` directive](https://caddyserver.com/docs/caddyfile/directives/forward_auth) allows Caddy to authenticate requests via the `oauth2-proxy`'s `/auth`. + +This example is for a simple reverse proxy setup where the `/oauth2/` path is kept under the same domain and failed auth requests (401 status returned) will be caught and redirected to the `sign_in` endpoint. + +**Following options need to be set on `oauth2-proxy`:** +- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly + +```nginx title="Caddyfile" +example.com { + # Requests to /oauth2/* are proxied to oauth2-proxy without authentication. + # You can't use `reverse_proxy /oauth2/* oauth2-proxy.internal:4180` here because the reverse_proxy directive has lower precedence than the handle directive. + handle /oauth2/* { + reverse_proxy oauth2-proxy.internal:4180 { + # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. + # The reverse_proxy directive automatically sets X-Forwarded-{For,Proto,Host} headers. + header_up X-Real-IP {remote_host} + header_up X-Forwarded-Uri {uri} + } + } + + # Requests to other paths are first processed by oauth2-proxy for authentication. + handle { + forward_auth oauth2-proxy.internal:4180 { + uri /oauth2/auth + + # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. + # The forward_auth directive automatically sets the X-Forwarded-{For,Proto,Host,Method,Uri} headers. + header_up X-Real-IP {remote_host} + + # If needed, you can copy headers from the oauth2-proxy response to the request sent to the upstream. + # Make sure to configure the --set-xauthrequest flag to enable this feature. + #copy_headers X-Auth-Request-User X-Auth-Request-Email + + # If oauth2-proxy returns a 401 status, redirect the client to the sign-in page. + @error status 401 + handle_response @error { + redir * /oauth2/sign_in?rd={scheme}://{host}{uri} + } + } + + # If oauth2-proxy returns a 2xx status, the request is then proxied to the upstream. + reverse_proxy upstream.internal:3000 + } +} +``` + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.13.x/configuration/integrations/headlamp.md b/docs/versioned_docs/version-7.13.x/configuration/integrations/headlamp.md new file mode 100644 index 00000000..a6f6ac73 --- /dev/null +++ b/docs/versioned_docs/version-7.13.x/configuration/integrations/headlamp.md @@ -0,0 +1,105 @@ +--- +id: headlamp +title: Headlamp +--- + +Modern, actively maintained Kubernetes web UI with OAuth2 Proxy integration examples. + +**Key features:** +- Active development and maintenance +- Modern, intuitive interface +- Multi-cluster support +- Plugin system +- Works with all OAuth2 providers + +## Configuring for use with Headlamp + +[Headlamp](https://headlamp.dev/) is a modern, user-friendly Kubernetes web UI that can be integrated with OAuth2 Proxy for authentication. This is a recommended alternative to the deprecated Kubernetes Dashboard. + +### Architecture + +``` +User → Ingress → OAuth2 Proxy → Authentication Provider (e.g., Azure Entra ID) + ↓ + Headlamp +``` + +### Prerequisites + +- Kubernetes cluster (e.g., AKS, EKS, GKE, or self-hosted) +- Headlamp installed in the cluster +- OAuth2 provider configured (Azure Entra ID, Google, GitHub, etc.) +- Ingress controller (Nginx, Traefik, etc.) + +### Configuration Overview + +When integrating Headlamp with OAuth2 Proxy, the OAuth2 Proxy acts as a reverse proxy in front of Headlamp: + +1. User requests access to Headlamp +2. Ingress forwards to OAuth2 Proxy +3. OAuth2 Proxy authenticates the user via the OAuth2 provider +4. After successful authentication, OAuth2 Proxy proxies requests to Headlamp +5. Headlamp receives the authenticated user information via headers + +### OAuth2 Proxy Configuration + +Configure OAuth2 Proxy to proxy to the Headlamp service: + +```yaml +upstreamConfig: + upstreams: + - id: headlamp + path: / + uri: http://headlamp-service.headlamp-namespace.svc.cluster.local:4466 +``` + +Enable the necessary headers: + +```yaml +extraArgs: + reverse-proxy: true + pass-authorization-header: true + set-xauthrequest: true + email-domain: "*" # Or restrict to your organization +``` + +### Example with Azure Entra ID on AKS + +For detailed instructions on deploying Headlamp with OAuth2 Proxy on Azure Kubernetes Service using Azure Entra ID, see the official Headlamp documentation: + +https://headlamp.dev/docs/latest/installation/in-cluster/aks-cluster-oauth/ + +Key steps include: + +1. **Set up AKS with OIDC**: Enable Microsoft Entra ID authentication with Kubernetes RBAC +2. **Create Azure App Registration**: Configure redirect URI and create client secret +3. **Deploy Headlamp**: Install Headlamp via Helm in your cluster +4. **Deploy OAuth2 Proxy**: Configure OAuth2 Proxy with Entra ID provider settings and upstream pointing to Headlamp +5. **Configure Ingress**: Set up Ingress to route traffic through OAuth2 Proxy to Headlamp +6. **Set RBAC Policies**: Apply Kubernetes RBAC bindings based on users or groups + +### Integration with Other Providers + +The same integration pattern works with other OAuth2 providers supported by OAuth2 Proxy: + +- **Google**: Use the Google provider configuration +- **GitHub**: Use the GitHub provider configuration +- **GitLab**: Use the GitLab provider configuration +- **Keycloak**: Use the Keycloak OIDC provider configuration +- **Any OIDC Provider**: Use the generic OIDC provider configuration + +For provider-specific configuration examples, see the [OAuth Provider Configuration](../providers/index.md) documentation. + +### Benefits Over Kubernetes Dashboard + +Headlamp offers several advantages: + +- **Active Development**: Headlamp is actively maintained and developed +- **Modern UI**: Clean, intuitive interface with better UX +- **Plugin System**: Extensible with custom plugins +- **Multi-cluster Support**: Built-in support for managing multiple clusters +- **Desktop App**: Available as both web UI and desktop application + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.13.x/configuration/integrations/index.md b/docs/versioned_docs/version-7.13.x/configuration/integrations/index.md new file mode 100644 index 00000000..b773910b --- /dev/null +++ b/docs/versioned_docs/version-7.13.x/configuration/integrations/index.md @@ -0,0 +1,41 @@ +--- +id: index +title: Integrations +--- + +This section provides configuration examples for integrating OAuth2 Proxy with various reverse proxies, ingress controllers, and Kubernetes web UIs. + +## Reverse Proxies and Ingress Controllers + +OAuth2 Proxy can be integrated with popular reverse proxies and ingress controllers to add authentication to your applications: + +- [Nginx](nginx.md) +- [Traefik](traefik.md) +- [caddy](caddy.md) + +## Kubernetes Web UIs + +OAuth2 Proxy can also be used to add authentication to Kubernetes web user interfaces: + +- [Headlamp](headlamp.md) ✨ *Recommended* +- [Kubernetes Dashboard](kubernetes-dashboard.md) ⚠️ *Deprecated* + +:::tip +When integrating with Kubernetes web UIs, make sure to: +1. Configure the Ingress to pass the Authorization header with the bearer token +2. Increase buffer sizes for large OIDC tokens (especially with Azure Entra ID) +3. Set up appropriate Kubernetes RBAC permissions for your users or groups +::: + +## General Requirements + +Most integrations require the following OAuth2 Proxy configuration: + +- `--reverse-proxy=true`: Required to correctly handle `X-Forwarded-*` headers +- **Session storage**: For production deployments with large tokens due to a lot of claims like AD groups, use `--session-store-type=redis` + +For provider-specific configuration, see the [OAuth Provider Configuration](../providers/index.md) documentation. + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.13.x/configuration/integrations/kubernetes-dashboard.md b/docs/versioned_docs/version-7.13.x/configuration/integrations/kubernetes-dashboard.md new file mode 100644 index 00000000..5f210768 --- /dev/null +++ b/docs/versioned_docs/version-7.13.x/configuration/integrations/kubernetes-dashboard.md @@ -0,0 +1,289 @@ +--- +id: kubernetes-dashboard +title: Kubernetes Dashboard +--- + +:::warning Deprecated Project +Kubernetes Dashboard has been deprecated and discontinued as of January 2025. See the [official announcement](https://github.com/kubernetes/dashboard/commit/0ba796dce6916bb6ca5da5ca0b3ab22cecfd1e18) for more information. + +You may want to consider alternative solutions such as [Headlamp](./headlamp.md). +::: + +## Kubernetes Dashboard on AKS with Azure Entra ID + +Integration guide for the deprecated Kubernetes Dashboard, including comprehensive Azure Entra ID configuration on AKS with detailed troubleshooting and RBAC setup. + +### Architecture + +``` +User → Nginx Ingress → OAuth2 Proxy → Entra ID + ↓ + Kubernetes Dashboard +``` + +The integration flow: +1. Unauthenticated requests to Dashboard are intercepted by Nginx Ingress +2. Nginx redirects to OAuth2 Proxy for authentication +3. OAuth2 Proxy redirects to Entra ID login +4. After successful authentication, OAuth2 Proxy receives ID token from Entra ID +5. OAuth2 Proxy sets Authorization header with the bearer token +6. Nginx forwards the request with token to Kubernetes Dashboard +7. Dashboard validates the token and grants access based on AKS RBAC configuration + +### Prerequisites + +- AKS cluster with Entra ID integration enabled +- Kubernetes Dashboard installed (version 7.x or later) +- NGINX Ingress Controller installed +- Entra ID App Registration configured with: + - Redirect URI: `https://your-oauth2-domain.com/oauth2/callback` + - API Permissions: `openid`, `email`, `profile` + - Groups claim enabled (if using group-based RBAC) +- Users or groups assigned appropriate Kubernetes RBAC permissions + +### Alpha Configuration Example + +Using [Alpha Configuration](../alpha_config.md) with the OAuth2 Proxy Helm chart: + +```yaml +alphaConfig: + enabled: true + configData: + providers: + - id: azure-entra + provider: entra-id + clientID: YOUR_CLIENT_ID + clientSecret: YOUR_CLIENT_SECRET + oidcConfig: + issuerURL: https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0 + audienceClaims: + - aud + emailClaim: email + groupsClaim: groups + userIDClaim: oid + scope: openid email profile + + upstreamConfig: + upstreams: + - id: static + path: / + static: true + staticCode: 200 + + # Response headers passed to Dashboard via Nginx + injectResponseHeaders: + - name: Authorization + values: + - claim: id_token + prefix: "Bearer " + - name: X-Auth-Request-User + values: + - claim: email + - name: X-Auth-Request-Email + values: + - claim: email + - name: X-Auth-Request-Groups + values: + - claim: groups + + server: + BindAddress: "0.0.0.0:4180" + +extraArgs: + cookie-domain: ".your-domain.com" + whitelist-domain: ".your-domain.com" + email-domain: "*" # Or restrict to your organization + skip-provider-button: true + reverse-proxy: true + pass-authorization-header: true + set-xauthrequest: true + +sessionStorage: + type: redis + +redis: + enabled: true + auth: + enabled: true + +ingress: + enabled: true + className: nginx + hosts: + - OAuth2 Proxy.your-domain.com + path: /oauth2 + pathType: Prefix +``` + +### Kubernetes Dashboard Ingress + +**Critical**: The Ingress must include `Authorization` in the `auth-response-headers` annotation: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: kubernetes-dashboard + namespace: kubernetes-dashboard + annotations: + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + + # OAuth2 Proxy authentication + nginx.ingress.kubernetes.io/auth-url: "https://OAuth2 Proxy.your-domain.com/oauth2/auth" + nginx.ingress.kubernetes.io/auth-signin: "https://OAuth2 Proxy.your-domain.com/oauth2/start?rd=$scheme://$best_http_host$request_uri" + + # Include Authorization header with bearer token + nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Auth-Request-User, X-Auth-Request-Email" + + # Buffer sizes for large tokens (Entra tokens can exceed 4KB) + nginx.ingress.kubernetes.io/proxy-buffer-size: "256k" + nginx.ingress.kubernetes.io/proxy-buffers-number: "4" + nginx.ingress.kubernetes.io/proxy-busy-buffers-size: "256k" +spec: + ingressClassName: nginx + tls: + - hosts: + - dashboard.your-domain.com + secretName: dashboard-tls + rules: + - host: dashboard.your-domain.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: kubernetes-dashboard-kong-proxy + port: + number: 443 +``` + +### RBAC Configuration + +Assign Kubernetes permissions to Entra ID users or groups. + +**User-based:** +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dashboard-user-admin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: User + name: "user@your-domain.com" # Email from Entra ID token + apiGroup: rbac.authorization.k8s.io +``` + +**Group-based (recommended):** +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dashboard-admins-group +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: Group + name: "YOUR_ENTRA_GROUP_OBJECT_ID" # Entra ID Group Object ID + apiGroup: rbac.authorization.k8s.io +``` + +For production, create custom roles with limited permissions instead of using `cluster-admin`. + +### Troubleshooting + +**Dashboard still asks for token after authentication** + +Verify that: +1. `injectResponseHeaders` in alphaConfig includes Authorization header with id_token claim +2. Dashboard Ingress includes `Authorization` in `auth-response-headers` annotation +3. Buffer sizes are sufficient for large tokens (set to 256k as shown above) +4. Check OAuth2 Proxy logs for successful token generation: `kubectl logs -n OAuth2 Proxy ` + +**"Unauthorized" or "Invalid token" errors** + +Common causes: +1. User/group not configured in Kubernetes RBAC + - Check: `kubectl get clusterrolebindings | grep ` +2. Token validation failed + - Verify AKS Entra ID integration is enabled + - Check Dashboard logs: `kubectl logs -n kubernetes-dashboard ` +3. Incorrect OAuth2 Proxy configuration + - Ensure `reverse-proxy: true` is set + - Verify issuer URL matches your tenant + +**Groups not included in token** + +To include groups in the token: +1. In Entra ID App Registration, go to **Token configuration** +2. Add **groups claim** and select security groups +3. Or edit the manifest and add: `"groupMembershipClaims": "SecurityGroup"` +4. For 200+ groups, ensure scope includes `User.Read` for group overage handling +5. Verify groups appear in token: check OAuth2 Proxy logs + +**Session expires too quickly** + +Configure cookie expiration: +```yaml +extraArgs: + cookie-expire: "24h" + cookie-refresh: "1h" +``` + +### Using Workload Identity (Passwordless) + +For production environments, use Workload Identity instead of client secrets: + +```yaml +config: + clientID: "YOUR_CLIENT_ID" + secretKeys: # Exclude client-secret + - client-id + - cookie-secret + cookieSecret: "YOUR_COOKIE_SECRET" + +serviceAccount: + annotations: + azure.workload.identity/client-id: YOUR_CLIENT_ID + azure.workload.identity/tenant-id: YOUR_TENANT_ID + +podLabels: + azure.workload.identity/use: "true" + +alphaConfig: + enabled: true + configData: + providers: + - id: azure-entra + provider: entra-id + clientID: YOUR_CLIENT_ID + oidcConfig: + issuerURL: https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0 + # ... other config + entraIdConfig: + federatedTokenAuth: true +``` + +This requires: +- AKS with OIDC issuer and Workload Identity enabled +- Federated identity credential configured in Entra ID App Registration +- Service account annotated with `azure.workload.identity/client-id` + +For detailed Workload Identity setup instructions, see the [Workload Identity section](../providers/ms_entra_id.md#workload-identity) in the Microsoft Entra ID provider documentation. + +## Integration with Other Providers + +While this guide focuses on Azure Entra ID, Kubernetes Dashboard can be integrated with other OAuth2 providers supported by OAuth2 Proxy. The key requirements remain the same: + +1. **Authorization Header**: Pass the bearer token via the `Authorization` header +2. **RBAC Configuration**: Configure Kubernetes RBAC for your authentication provider's users/groups +3. **Buffer Sizes**: Ensure adequate buffer sizes for tokens (especially important for OIDC providers) + +For provider-specific configuration examples, see the [OAuth Provider Configuration](../providers/index.md) documentation. diff --git a/docs/versioned_docs/version-7.13.x/configuration/integrations/nginx.md b/docs/versioned_docs/version-7.13.x/configuration/integrations/nginx.md new file mode 100644 index 00000000..a36ed762 --- /dev/null +++ b/docs/versioned_docs/version-7.13.x/configuration/integrations/nginx.md @@ -0,0 +1,107 @@ +--- +id: nginx +title: Nginx +--- + +Configure OAuth2 Proxy with Nginx using the `auth_request` directive. Includes examples for both standalone Nginx configurations and Kubernetes ingress-nginx with annotations. + +**Key features:** +- Support for `auth_request` directive +- Kubernetes Ingress annotations +- Multi-part cookie handling for large tokens +- Session refresh support + +## Configuring for use with the Nginx `auth_request` directive + +**This option requires `--reverse-proxy` option to be set.** + +The [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) allows Nginx to authenticate requests via the oauth2-proxy's `/auth` endpoint, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the request through. For example: + +```nginx +server { + listen 443 ssl; + server_name ...; + include ssl/ssl.conf; + + location /oauth2/ { + proxy_pass http://127.0.0.1:4180; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Auth-Request-Redirect $request_uri; + # or, if you are handling multiple domains: + # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; + } + location = /oauth2/auth { + proxy_pass http://127.0.0.1:4180; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Uri $request_uri; + # nginx auth_request includes headers but not body + proxy_set_header Content-Length ""; + proxy_pass_request_body off; + } + + location / { + auth_request /oauth2/auth; + error_page 401 =403 /oauth2/sign_in; + + # pass information via X-User and X-Email headers to backend, + # requires running with --set-xauthrequest flag + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $email $upstream_http_x_auth_request_email; + proxy_set_header X-User $user; + proxy_set_header X-Email $email; + + # if you enabled --pass-access-token, this will pass the token to the backend + auth_request_set $token $upstream_http_x_auth_request_access_token; + proxy_set_header X-Access-Token $token; + + # if you enabled --cookie-refresh, this is needed for it to work with auth_request + auth_request_set $auth_cookie $upstream_http_set_cookie; + add_header Set-Cookie $auth_cookie; + + # When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb + # limit and so the OAuth2 Proxy splits these into multiple parts. + # Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response, + # so if your cookies are larger than 4kb, you will need to extract additional cookies manually. + auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1; + + # Extract the Cookie attributes from the first Set-Cookie header and append them + # to the second part ($upstream_cookie_* variables only contain the raw cookie content) + if ($auth_cookie ~* "(; .*)") { + set $auth_cookie_name_0 $auth_cookie; + set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1"; + } + + # Send both Set-Cookie headers now if there was a second part + if ($auth_cookie_name_upstream_1) { + add_header Set-Cookie $auth_cookie_name_0; + add_header Set-Cookie $auth_cookie_name_1; + } + + proxy_pass http://backend/; + # or "root /path/to/site;" or "fastcgi_pass ..." etc + } +} +``` + +When you use ingress-nginx in Kubernetes, you can configure the same behavior with the following annotations on your Ingress resource: + +```yaml +nginx.ingress.kubernetes.io/auth-url: "https:///oauth2/auth" +nginx.ingress.kubernetes.io/auth-signin: "https:///oauth2/start?rd=$escaped_request_uri" +``` + +This minimal configuration works for standard authentication flows. Lua/cookie handling is only needed for advanced scenarios (e.g., multi-part cookies, custom session logic). See the official ingress-nginx example: https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/. + +It is recommended to use `--session-store-type=redis` when expecting large sessions/OIDC tokens (_e.g._ with MS Azure). + +:::tip Kubernetes Dashboard with Azure Entra ID +For a complete example of integrating oauth2-proxy with Kubernetes Dashboard on AKS using Azure Entra ID, including RBAC configuration and troubleshooting, see the [Kubernetes Dashboard on AKS](../providers/ms_entra_id.md#kubernetes-dashboard-on-aks) section in the Microsoft Entra ID provider documentation. +::: + +You have to substitute *name* with the actual cookie name you configured via --cookie-name parameter. If you don't set a custom cookie name the variable should be "$upstream_cookie__oauth2_proxy_1" instead of "$upstream_cookie_name_1" and the new cookie-name should be "_oauth2_proxy_1=" instead of "name_1=". + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.13.x/configuration/integrations/traefik.md b/docs/versioned_docs/version-7.13.x/configuration/integrations/traefik.md new file mode 100644 index 00000000..e4b64b94 --- /dev/null +++ b/docs/versioned_docs/version-7.13.x/configuration/integrations/traefik.md @@ -0,0 +1,184 @@ +--- +id: traefik +title: Traefik +--- + +Set up OAuth2 Proxy with Traefik v2 using the `ForwardAuth` middleware. Includes examples for both error-based redirects and static upstream configurations. + +**Key features:** +- ForwardAuth middleware integration +- Error middleware for 401 redirects +- Static upstream configuration (202 responses) +- Dynamic file configuration examples + + +## Configuring for use with the Traefik (v2) `ForwardAuth` middleware + +**This option requires `--reverse-proxy` option to be set.** + +### ForwardAuth with 401 errors middleware + +The [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) allows Traefik to authenticate requests via the oauth2-proxy's `/oauth2/auth` endpoint on every request, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the whole request through. For example, on Dynamic File (YAML) Configuration: + +```yaml +http: + routers: + a-service: + rule: "Host(`a-service.example.com`)" + service: a-service-backend + middlewares: + - oauth-errors + - oauth-auth + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + oauth: + rule: "Host(`a-service.example.com`, `oauth.example.com`) && PathPrefix(`/oauth2/`)" + middlewares: + - auth-headers + service: oauth-backend + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + + services: + a-service-backend: + loadBalancer: + servers: + - url: http://172.16.0.2:7555 + oauth-backend: + loadBalancer: + servers: + - url: http://172.16.0.1:4180 + + middlewares: + auth-headers: + headers: + sslRedirect: true + stsSeconds: 315360000 + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + sslHost: example.com + stsIncludeSubdomains: true + stsPreload: true + frameDeny: true + oauth-auth: + forwardAuth: + address: https://oauth.example.com/oauth2/auth + trustForwardHeader: true + oauth-errors: + errors: + status: + - "401-403" + service: oauth-backend + query: "/oauth2/sign_in?rd={url}" +``` + +### ForwardAuth with static upstreams configuration + +Redirect to sign_in functionality provided without the use of `errors` middleware with [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) pointing to oauth2-proxy service's `/` endpoint + +**Following options need to be set on `oauth2-proxy`:** +- `--upstream=static://202`: Configures a static response for authenticated sessions +- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly + +```yaml +http: + routers: + a-service-route-1: + rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/`)" + service: a-service-backend + middlewares: + - oauth-auth-redirect # redirects all unauthenticated to oauth2 signin + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + a-service-route-2: + rule: "Host(`a-service.example.com`) && PathPrefix(`/no-auto-redirect`)" + service: a-service-backend + middlewares: + - oauth-auth-wo-redirect # unauthenticated session will return a 401 + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + services-oauth2-route: + rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/oauth2/`)" + middlewares: + - auth-headers + service: oauth-backend + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + oauth2-proxy-route: + rule: "Host(`oauth.example.com`) && PathPrefix(`/`)" + middlewares: + - auth-headers + service: oauth-backend + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + + services: + a-service-backend: + loadBalancer: + servers: + - url: http://172.16.0.2:7555 + b-service-backend: + loadBalancer: + servers: + - url: http://172.16.0.3:7555 + oauth-backend: + loadBalancer: + servers: + - url: http://172.16.0.1:4180 + + middlewares: + auth-headers: + headers: + sslRedirect: true + stsSeconds: 315360000 + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + sslHost: example.com + stsIncludeSubdomains: true + stsPreload: true + frameDeny: true + oauth-auth-redirect: + forwardAuth: + address: https://oauth.example.com/ + trustForwardHeader: true + authResponseHeaders: + - X-Auth-Request-Access-Token + - Authorization + oauth-auth-wo-redirect: + forwardAuth: + address: https://oauth.example.com/oauth2/auth + trustForwardHeader: true + authResponseHeaders: + - X-Auth-Request-Access-Token + - Authorization +``` + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.13.x/features/endpoints.md b/docs/versioned_docs/version-7.13.x/features/endpoints.md index 3ec1e2aa..6052a7d3 100644 --- a/docs/versioned_docs/version-7.13.x/features/endpoints.md +++ b/docs/versioned_docs/version-7.13.x/features/endpoints.md @@ -14,7 +14,7 @@ OAuth2 Proxy responds directly to the following endpoints. All other endpoints w - /oauth2/start - a URL that will redirect to start the OAuth cycle - /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url. - /oauth2/userinfo - the URL is used to return user's email from the session in JSON format. -- /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](../configuration/integration#configuring-for-use-with-the-nginx-auth_request-directive) +- /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](../configuration/integrations/nginx) - /oauth2/static/\* - stylesheets and other dependencies used in the sign_in and error pages ### Sign out diff --git a/docs/versioned_docs/version-7.14.x/configuration/integration.md b/docs/versioned_docs/version-7.14.x/configuration/integration.md deleted file mode 100644 index c57cfa6b..00000000 --- a/docs/versioned_docs/version-7.14.x/configuration/integration.md +++ /dev/null @@ -1,310 +0,0 @@ ---- -id: integration -title: Integration ---- - -## Configuring for use with the Nginx `auth_request` directive - -**This option requires `--reverse-proxy` option to be set.** - -The [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) allows Nginx to authenticate requests via the oauth2-proxy's `/auth` endpoint, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the request through. For example: - -```nginx -server { - listen 443 ssl; - server_name ...; - include ssl/ssl.conf; - - location /oauth2/ { - proxy_pass http://127.0.0.1:4180; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Auth-Request-Redirect $request_uri; - # or, if you are handling multiple domains: - # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; - } - location = /oauth2/auth { - proxy_pass http://127.0.0.1:4180; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Uri $request_uri; - # nginx auth_request includes headers but not body - proxy_set_header Content-Length ""; - proxy_pass_request_body off; - } - - location / { - auth_request /oauth2/auth; - error_page 401 =403 /oauth2/sign_in; - - # pass information via X-User and X-Email headers to backend, - # requires running with --set-xauthrequest flag - auth_request_set $user $upstream_http_x_auth_request_user; - auth_request_set $email $upstream_http_x_auth_request_email; - proxy_set_header X-User $user; - proxy_set_header X-Email $email; - - # if you enabled --pass-access-token, this will pass the token to the backend - auth_request_set $token $upstream_http_x_auth_request_access_token; - proxy_set_header X-Access-Token $token; - - # if you enabled --cookie-refresh, this is needed for it to work with auth_request - auth_request_set $auth_cookie $upstream_http_set_cookie; - add_header Set-Cookie $auth_cookie; - - # When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb - # limit and so the OAuth2 Proxy splits these into multiple parts. - # Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response, - # so if your cookies are larger than 4kb, you will need to extract additional cookies manually. - auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1; - - # Extract the Cookie attributes from the first Set-Cookie header and append them - # to the second part ($upstream_cookie_* variables only contain the raw cookie content) - if ($auth_cookie ~* "(; .*)") { - set $auth_cookie_name_0 $auth_cookie; - set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1"; - } - - # Send both Set-Cookie headers now if there was a second part - if ($auth_cookie_name_upstream_1) { - add_header Set-Cookie $auth_cookie_name_0; - add_header Set-Cookie $auth_cookie_name_1; - } - - proxy_pass http://backend/; - # or "root /path/to/site;" or "fastcgi_pass ..." etc - } -} -``` - -When you use ingress-nginx in Kubernetes, you can configure the same behavior with the following annotations on your Ingress resource: - -```yaml -nginx.ingress.kubernetes.io/auth-url: "https:///oauth2/auth" -nginx.ingress.kubernetes.io/auth-signin: "https:///oauth2/start?rd=$escaped_request_uri" -``` - -This minimal configuration works for standard authentication flows. Lua/cookie handling is only needed for advanced scenarios (e.g., multi-part cookies, custom session logic). See the official ingress-nginx example: https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/. - -It is recommended to use `--session-store-type=redis` when expecting large sessions/OIDC tokens (_e.g._ with MS Azure). - -You have to substitute *name* with the actual cookie name you configured via --cookie-name parameter. If you don't set a custom cookie name the variable should be "$upstream_cookie__oauth2_proxy_1" instead of "$upstream_cookie_name_1" and the new cookie-name should be "_oauth2_proxy_1=" instead of "name_1=". - -## Configuring for use with the Traefik (v2) `ForwardAuth` middleware - -**This option requires `--reverse-proxy` option to be set.** - -### ForwardAuth with 401 errors middleware - -The [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) allows Traefik to authenticate requests via the oauth2-proxy's `/oauth2/auth` endpoint on every request, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the whole request through. For example, on Dynamic File (YAML) Configuration: - -```yaml -http: - routers: - a-service: - rule: "Host(`a-service.example.com`)" - service: a-service-backend - middlewares: - - oauth-errors - - oauth-auth - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - oauth: - rule: "Host(`a-service.example.com`, `oauth.example.com`) && PathPrefix(`/oauth2/`)" - middlewares: - - auth-headers - service: oauth-backend - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - - services: - a-service-backend: - loadBalancer: - servers: - - url: http://172.16.0.2:7555 - oauth-backend: - loadBalancer: - servers: - - url: http://172.16.0.1:4180 - - middlewares: - auth-headers: - headers: - sslRedirect: true - stsSeconds: 315360000 - browserXssFilter: true - contentTypeNosniff: true - forceSTSHeader: true - sslHost: example.com - stsIncludeSubdomains: true - stsPreload: true - frameDeny: true - oauth-auth: - forwardAuth: - address: https://oauth.example.com/oauth2/auth - trustForwardHeader: true - oauth-errors: - errors: - status: - - "401-403" - service: oauth-backend - query: "/oauth2/sign_in?rd={url}" -``` - -### ForwardAuth with static upstreams configuration - -Redirect to sign_in functionality provided without the use of `errors` middleware with [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) pointing to oauth2-proxy service's `/` endpoint - -**Following options need to be set on `oauth2-proxy`:** -- `--upstream=static://202`: Configures a static response for authenticated sessions -- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly - -```yaml -http: - routers: - a-service-route-1: - rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/`)" - service: a-service-backend - middlewares: - - oauth-auth-redirect # redirects all unauthenticated to oauth2 signin - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - a-service-route-2: - rule: "Host(`a-service.example.com`) && PathPrefix(`/no-auto-redirect`)" - service: a-service-backend - middlewares: - - oauth-auth-wo-redirect # unauthenticated session will return a 401 - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - services-oauth2-route: - rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/oauth2/`)" - middlewares: - - auth-headers - service: oauth-backend - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - oauth2-proxy-route: - rule: "Host(`oauth.example.com`) && PathPrefix(`/`)" - middlewares: - - auth-headers - service: oauth-backend - tls: - certResolver: default - domains: - - main: "example.com" - sans: - - "*.example.com" - - services: - a-service-backend: - loadBalancer: - servers: - - url: http://172.16.0.2:7555 - b-service-backend: - loadBalancer: - servers: - - url: http://172.16.0.3:7555 - oauth-backend: - loadBalancer: - servers: - - url: http://172.16.0.1:4180 - - middlewares: - auth-headers: - headers: - sslRedirect: true - stsSeconds: 315360000 - browserXssFilter: true - contentTypeNosniff: true - forceSTSHeader: true - sslHost: example.com - stsIncludeSubdomains: true - stsPreload: true - frameDeny: true - oauth-auth-redirect: - forwardAuth: - address: https://oauth.example.com/ - trustForwardHeader: true - authResponseHeaders: - - X-Auth-Request-Access-Token - - Authorization - oauth-auth-wo-redirect: - forwardAuth: - address: https://oauth.example.com/oauth2/auth - trustForwardHeader: true - authResponseHeaders: - - X-Auth-Request-Access-Token - - Authorization -``` - -## Configuring for use with the Caddy (v2) `forward_auth` directive - -The [Caddy `forward_auth` directive](https://caddyserver.com/docs/caddyfile/directives/forward_auth) allows Caddy to authenticate requests via the `oauth2-proxy`'s `/auth`. - -This example is for a simple reverse proxy setup where the `/oauth2/` path is kept under the same domain and failed auth requests (401 status returned) will be caught and redirected to the `sign_in` endpoint. - -**Following options need to be set on `oauth2-proxy`:** -- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly - -```nginx title="Caddyfile" -example.com { - # Requests to /oauth2/* are proxied to oauth2-proxy without authentication. - # You can't use `reverse_proxy /oauth2/* oauth2-proxy.internal:4180` here because the reverse_proxy directive has lower precedence than the handle directive. - handle /oauth2/* { - reverse_proxy oauth2-proxy.internal:4180 { - # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. - # The reverse_proxy directive automatically sets X-Forwarded-{For,Proto,Host} headers. - header_up X-Real-IP {remote_host} - header_up X-Forwarded-Uri {uri} - } - } - - # Requests to other paths are first processed by oauth2-proxy for authentication. - handle { - forward_auth oauth2-proxy.internal:4180 { - uri /oauth2/auth - - # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. - # The forward_auth directive automatically sets the X-Forwarded-{For,Proto,Host,Method,Uri} headers. - header_up X-Real-IP {remote_host} - - # If needed, you can copy headers from the oauth2-proxy response to the request sent to the upstream. - # Make sure to configure the --set-xauthrequest flag to enable this feature. - #copy_headers X-Auth-Request-User X-Auth-Request-Email - - # If oauth2-proxy returns a 401 status, redirect the client to the sign-in page. - @error status 401 - handle_response @error { - redir * /oauth2/sign_in?rd={scheme}://{host}{uri} - } - } - - # If oauth2-proxy returns a 2xx status, the request is then proxied to the upstream. - reverse_proxy upstream.internal:3000 - } -} -``` - -:::note -If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. -::: diff --git a/docs/versioned_docs/version-7.14.x/configuration/integrations/caddy.md b/docs/versioned_docs/version-7.14.x/configuration/integrations/caddy.md new file mode 100644 index 00000000..1805e559 --- /dev/null +++ b/docs/versioned_docs/version-7.14.x/configuration/integrations/caddy.md @@ -0,0 +1,63 @@ +--- +id: caddy +title: Caddy +--- + +Integrate OAuth2 Proxy with Caddy v2 using the `forward_auth` directive. + +**Key features:** +- Simple forward_auth setup +- Automatic header handling +- Custom error handling and redirects + +## Configuring for use with the Caddy (v2) `forward_auth` directive + +The [Caddy `forward_auth` directive](https://caddyserver.com/docs/caddyfile/directives/forward_auth) allows Caddy to authenticate requests via the `oauth2-proxy`'s `/auth`. + +This example is for a simple reverse proxy setup where the `/oauth2/` path is kept under the same domain and failed auth requests (401 status returned) will be caught and redirected to the `sign_in` endpoint. + +**Following options need to be set on `oauth2-proxy`:** +- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly + +```nginx title="Caddyfile" +example.com { + # Requests to /oauth2/* are proxied to oauth2-proxy without authentication. + # You can't use `reverse_proxy /oauth2/* oauth2-proxy.internal:4180` here because the reverse_proxy directive has lower precedence than the handle directive. + handle /oauth2/* { + reverse_proxy oauth2-proxy.internal:4180 { + # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. + # The reverse_proxy directive automatically sets X-Forwarded-{For,Proto,Host} headers. + header_up X-Real-IP {remote_host} + header_up X-Forwarded-Uri {uri} + } + } + + # Requests to other paths are first processed by oauth2-proxy for authentication. + handle { + forward_auth oauth2-proxy.internal:4180 { + uri /oauth2/auth + + # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers. + # The forward_auth directive automatically sets the X-Forwarded-{For,Proto,Host,Method,Uri} headers. + header_up X-Real-IP {remote_host} + + # If needed, you can copy headers from the oauth2-proxy response to the request sent to the upstream. + # Make sure to configure the --set-xauthrequest flag to enable this feature. + #copy_headers X-Auth-Request-User X-Auth-Request-Email + + # If oauth2-proxy returns a 401 status, redirect the client to the sign-in page. + @error status 401 + handle_response @error { + redir * /oauth2/sign_in?rd={scheme}://{host}{uri} + } + } + + # If oauth2-proxy returns a 2xx status, the request is then proxied to the upstream. + reverse_proxy upstream.internal:3000 + } +} +``` + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.14.x/configuration/integrations/headlamp.md b/docs/versioned_docs/version-7.14.x/configuration/integrations/headlamp.md new file mode 100644 index 00000000..a6f6ac73 --- /dev/null +++ b/docs/versioned_docs/version-7.14.x/configuration/integrations/headlamp.md @@ -0,0 +1,105 @@ +--- +id: headlamp +title: Headlamp +--- + +Modern, actively maintained Kubernetes web UI with OAuth2 Proxy integration examples. + +**Key features:** +- Active development and maintenance +- Modern, intuitive interface +- Multi-cluster support +- Plugin system +- Works with all OAuth2 providers + +## Configuring for use with Headlamp + +[Headlamp](https://headlamp.dev/) is a modern, user-friendly Kubernetes web UI that can be integrated with OAuth2 Proxy for authentication. This is a recommended alternative to the deprecated Kubernetes Dashboard. + +### Architecture + +``` +User → Ingress → OAuth2 Proxy → Authentication Provider (e.g., Azure Entra ID) + ↓ + Headlamp +``` + +### Prerequisites + +- Kubernetes cluster (e.g., AKS, EKS, GKE, or self-hosted) +- Headlamp installed in the cluster +- OAuth2 provider configured (Azure Entra ID, Google, GitHub, etc.) +- Ingress controller (Nginx, Traefik, etc.) + +### Configuration Overview + +When integrating Headlamp with OAuth2 Proxy, the OAuth2 Proxy acts as a reverse proxy in front of Headlamp: + +1. User requests access to Headlamp +2. Ingress forwards to OAuth2 Proxy +3. OAuth2 Proxy authenticates the user via the OAuth2 provider +4. After successful authentication, OAuth2 Proxy proxies requests to Headlamp +5. Headlamp receives the authenticated user information via headers + +### OAuth2 Proxy Configuration + +Configure OAuth2 Proxy to proxy to the Headlamp service: + +```yaml +upstreamConfig: + upstreams: + - id: headlamp + path: / + uri: http://headlamp-service.headlamp-namespace.svc.cluster.local:4466 +``` + +Enable the necessary headers: + +```yaml +extraArgs: + reverse-proxy: true + pass-authorization-header: true + set-xauthrequest: true + email-domain: "*" # Or restrict to your organization +``` + +### Example with Azure Entra ID on AKS + +For detailed instructions on deploying Headlamp with OAuth2 Proxy on Azure Kubernetes Service using Azure Entra ID, see the official Headlamp documentation: + +https://headlamp.dev/docs/latest/installation/in-cluster/aks-cluster-oauth/ + +Key steps include: + +1. **Set up AKS with OIDC**: Enable Microsoft Entra ID authentication with Kubernetes RBAC +2. **Create Azure App Registration**: Configure redirect URI and create client secret +3. **Deploy Headlamp**: Install Headlamp via Helm in your cluster +4. **Deploy OAuth2 Proxy**: Configure OAuth2 Proxy with Entra ID provider settings and upstream pointing to Headlamp +5. **Configure Ingress**: Set up Ingress to route traffic through OAuth2 Proxy to Headlamp +6. **Set RBAC Policies**: Apply Kubernetes RBAC bindings based on users or groups + +### Integration with Other Providers + +The same integration pattern works with other OAuth2 providers supported by OAuth2 Proxy: + +- **Google**: Use the Google provider configuration +- **GitHub**: Use the GitHub provider configuration +- **GitLab**: Use the GitLab provider configuration +- **Keycloak**: Use the Keycloak OIDC provider configuration +- **Any OIDC Provider**: Use the generic OIDC provider configuration + +For provider-specific configuration examples, see the [OAuth Provider Configuration](../providers/index.md) documentation. + +### Benefits Over Kubernetes Dashboard + +Headlamp offers several advantages: + +- **Active Development**: Headlamp is actively maintained and developed +- **Modern UI**: Clean, intuitive interface with better UX +- **Plugin System**: Extensible with custom plugins +- **Multi-cluster Support**: Built-in support for managing multiple clusters +- **Desktop App**: Available as both web UI and desktop application + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.14.x/configuration/integrations/index.md b/docs/versioned_docs/version-7.14.x/configuration/integrations/index.md new file mode 100644 index 00000000..b773910b --- /dev/null +++ b/docs/versioned_docs/version-7.14.x/configuration/integrations/index.md @@ -0,0 +1,41 @@ +--- +id: index +title: Integrations +--- + +This section provides configuration examples for integrating OAuth2 Proxy with various reverse proxies, ingress controllers, and Kubernetes web UIs. + +## Reverse Proxies and Ingress Controllers + +OAuth2 Proxy can be integrated with popular reverse proxies and ingress controllers to add authentication to your applications: + +- [Nginx](nginx.md) +- [Traefik](traefik.md) +- [caddy](caddy.md) + +## Kubernetes Web UIs + +OAuth2 Proxy can also be used to add authentication to Kubernetes web user interfaces: + +- [Headlamp](headlamp.md) ✨ *Recommended* +- [Kubernetes Dashboard](kubernetes-dashboard.md) ⚠️ *Deprecated* + +:::tip +When integrating with Kubernetes web UIs, make sure to: +1. Configure the Ingress to pass the Authorization header with the bearer token +2. Increase buffer sizes for large OIDC tokens (especially with Azure Entra ID) +3. Set up appropriate Kubernetes RBAC permissions for your users or groups +::: + +## General Requirements + +Most integrations require the following OAuth2 Proxy configuration: + +- `--reverse-proxy=true`: Required to correctly handle `X-Forwarded-*` headers +- **Session storage**: For production deployments with large tokens due to a lot of claims like AD groups, use `--session-store-type=redis` + +For provider-specific configuration, see the [OAuth Provider Configuration](../providers/index.md) documentation. + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.14.x/configuration/integrations/kubernetes-dashboard.md b/docs/versioned_docs/version-7.14.x/configuration/integrations/kubernetes-dashboard.md new file mode 100644 index 00000000..5f210768 --- /dev/null +++ b/docs/versioned_docs/version-7.14.x/configuration/integrations/kubernetes-dashboard.md @@ -0,0 +1,289 @@ +--- +id: kubernetes-dashboard +title: Kubernetes Dashboard +--- + +:::warning Deprecated Project +Kubernetes Dashboard has been deprecated and discontinued as of January 2025. See the [official announcement](https://github.com/kubernetes/dashboard/commit/0ba796dce6916bb6ca5da5ca0b3ab22cecfd1e18) for more information. + +You may want to consider alternative solutions such as [Headlamp](./headlamp.md). +::: + +## Kubernetes Dashboard on AKS with Azure Entra ID + +Integration guide for the deprecated Kubernetes Dashboard, including comprehensive Azure Entra ID configuration on AKS with detailed troubleshooting and RBAC setup. + +### Architecture + +``` +User → Nginx Ingress → OAuth2 Proxy → Entra ID + ↓ + Kubernetes Dashboard +``` + +The integration flow: +1. Unauthenticated requests to Dashboard are intercepted by Nginx Ingress +2. Nginx redirects to OAuth2 Proxy for authentication +3. OAuth2 Proxy redirects to Entra ID login +4. After successful authentication, OAuth2 Proxy receives ID token from Entra ID +5. OAuth2 Proxy sets Authorization header with the bearer token +6. Nginx forwards the request with token to Kubernetes Dashboard +7. Dashboard validates the token and grants access based on AKS RBAC configuration + +### Prerequisites + +- AKS cluster with Entra ID integration enabled +- Kubernetes Dashboard installed (version 7.x or later) +- NGINX Ingress Controller installed +- Entra ID App Registration configured with: + - Redirect URI: `https://your-oauth2-domain.com/oauth2/callback` + - API Permissions: `openid`, `email`, `profile` + - Groups claim enabled (if using group-based RBAC) +- Users or groups assigned appropriate Kubernetes RBAC permissions + +### Alpha Configuration Example + +Using [Alpha Configuration](../alpha_config.md) with the OAuth2 Proxy Helm chart: + +```yaml +alphaConfig: + enabled: true + configData: + providers: + - id: azure-entra + provider: entra-id + clientID: YOUR_CLIENT_ID + clientSecret: YOUR_CLIENT_SECRET + oidcConfig: + issuerURL: https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0 + audienceClaims: + - aud + emailClaim: email + groupsClaim: groups + userIDClaim: oid + scope: openid email profile + + upstreamConfig: + upstreams: + - id: static + path: / + static: true + staticCode: 200 + + # Response headers passed to Dashboard via Nginx + injectResponseHeaders: + - name: Authorization + values: + - claim: id_token + prefix: "Bearer " + - name: X-Auth-Request-User + values: + - claim: email + - name: X-Auth-Request-Email + values: + - claim: email + - name: X-Auth-Request-Groups + values: + - claim: groups + + server: + BindAddress: "0.0.0.0:4180" + +extraArgs: + cookie-domain: ".your-domain.com" + whitelist-domain: ".your-domain.com" + email-domain: "*" # Or restrict to your organization + skip-provider-button: true + reverse-proxy: true + pass-authorization-header: true + set-xauthrequest: true + +sessionStorage: + type: redis + +redis: + enabled: true + auth: + enabled: true + +ingress: + enabled: true + className: nginx + hosts: + - OAuth2 Proxy.your-domain.com + path: /oauth2 + pathType: Prefix +``` + +### Kubernetes Dashboard Ingress + +**Critical**: The Ingress must include `Authorization` in the `auth-response-headers` annotation: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: kubernetes-dashboard + namespace: kubernetes-dashboard + annotations: + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + + # OAuth2 Proxy authentication + nginx.ingress.kubernetes.io/auth-url: "https://OAuth2 Proxy.your-domain.com/oauth2/auth" + nginx.ingress.kubernetes.io/auth-signin: "https://OAuth2 Proxy.your-domain.com/oauth2/start?rd=$scheme://$best_http_host$request_uri" + + # Include Authorization header with bearer token + nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Auth-Request-User, X-Auth-Request-Email" + + # Buffer sizes for large tokens (Entra tokens can exceed 4KB) + nginx.ingress.kubernetes.io/proxy-buffer-size: "256k" + nginx.ingress.kubernetes.io/proxy-buffers-number: "4" + nginx.ingress.kubernetes.io/proxy-busy-buffers-size: "256k" +spec: + ingressClassName: nginx + tls: + - hosts: + - dashboard.your-domain.com + secretName: dashboard-tls + rules: + - host: dashboard.your-domain.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: kubernetes-dashboard-kong-proxy + port: + number: 443 +``` + +### RBAC Configuration + +Assign Kubernetes permissions to Entra ID users or groups. + +**User-based:** +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dashboard-user-admin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: User + name: "user@your-domain.com" # Email from Entra ID token + apiGroup: rbac.authorization.k8s.io +``` + +**Group-based (recommended):** +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dashboard-admins-group +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: Group + name: "YOUR_ENTRA_GROUP_OBJECT_ID" # Entra ID Group Object ID + apiGroup: rbac.authorization.k8s.io +``` + +For production, create custom roles with limited permissions instead of using `cluster-admin`. + +### Troubleshooting + +**Dashboard still asks for token after authentication** + +Verify that: +1. `injectResponseHeaders` in alphaConfig includes Authorization header with id_token claim +2. Dashboard Ingress includes `Authorization` in `auth-response-headers` annotation +3. Buffer sizes are sufficient for large tokens (set to 256k as shown above) +4. Check OAuth2 Proxy logs for successful token generation: `kubectl logs -n OAuth2 Proxy ` + +**"Unauthorized" or "Invalid token" errors** + +Common causes: +1. User/group not configured in Kubernetes RBAC + - Check: `kubectl get clusterrolebindings | grep ` +2. Token validation failed + - Verify AKS Entra ID integration is enabled + - Check Dashboard logs: `kubectl logs -n kubernetes-dashboard ` +3. Incorrect OAuth2 Proxy configuration + - Ensure `reverse-proxy: true` is set + - Verify issuer URL matches your tenant + +**Groups not included in token** + +To include groups in the token: +1. In Entra ID App Registration, go to **Token configuration** +2. Add **groups claim** and select security groups +3. Or edit the manifest and add: `"groupMembershipClaims": "SecurityGroup"` +4. For 200+ groups, ensure scope includes `User.Read` for group overage handling +5. Verify groups appear in token: check OAuth2 Proxy logs + +**Session expires too quickly** + +Configure cookie expiration: +```yaml +extraArgs: + cookie-expire: "24h" + cookie-refresh: "1h" +``` + +### Using Workload Identity (Passwordless) + +For production environments, use Workload Identity instead of client secrets: + +```yaml +config: + clientID: "YOUR_CLIENT_ID" + secretKeys: # Exclude client-secret + - client-id + - cookie-secret + cookieSecret: "YOUR_COOKIE_SECRET" + +serviceAccount: + annotations: + azure.workload.identity/client-id: YOUR_CLIENT_ID + azure.workload.identity/tenant-id: YOUR_TENANT_ID + +podLabels: + azure.workload.identity/use: "true" + +alphaConfig: + enabled: true + configData: + providers: + - id: azure-entra + provider: entra-id + clientID: YOUR_CLIENT_ID + oidcConfig: + issuerURL: https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0 + # ... other config + entraIdConfig: + federatedTokenAuth: true +``` + +This requires: +- AKS with OIDC issuer and Workload Identity enabled +- Federated identity credential configured in Entra ID App Registration +- Service account annotated with `azure.workload.identity/client-id` + +For detailed Workload Identity setup instructions, see the [Workload Identity section](../providers/ms_entra_id.md#workload-identity) in the Microsoft Entra ID provider documentation. + +## Integration with Other Providers + +While this guide focuses on Azure Entra ID, Kubernetes Dashboard can be integrated with other OAuth2 providers supported by OAuth2 Proxy. The key requirements remain the same: + +1. **Authorization Header**: Pass the bearer token via the `Authorization` header +2. **RBAC Configuration**: Configure Kubernetes RBAC for your authentication provider's users/groups +3. **Buffer Sizes**: Ensure adequate buffer sizes for tokens (especially important for OIDC providers) + +For provider-specific configuration examples, see the [OAuth Provider Configuration](../providers/index.md) documentation. diff --git a/docs/versioned_docs/version-7.14.x/configuration/integrations/nginx.md b/docs/versioned_docs/version-7.14.x/configuration/integrations/nginx.md new file mode 100644 index 00000000..a36ed762 --- /dev/null +++ b/docs/versioned_docs/version-7.14.x/configuration/integrations/nginx.md @@ -0,0 +1,107 @@ +--- +id: nginx +title: Nginx +--- + +Configure OAuth2 Proxy with Nginx using the `auth_request` directive. Includes examples for both standalone Nginx configurations and Kubernetes ingress-nginx with annotations. + +**Key features:** +- Support for `auth_request` directive +- Kubernetes Ingress annotations +- Multi-part cookie handling for large tokens +- Session refresh support + +## Configuring for use with the Nginx `auth_request` directive + +**This option requires `--reverse-proxy` option to be set.** + +The [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) allows Nginx to authenticate requests via the oauth2-proxy's `/auth` endpoint, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the request through. For example: + +```nginx +server { + listen 443 ssl; + server_name ...; + include ssl/ssl.conf; + + location /oauth2/ { + proxy_pass http://127.0.0.1:4180; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Auth-Request-Redirect $request_uri; + # or, if you are handling multiple domains: + # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; + } + location = /oauth2/auth { + proxy_pass http://127.0.0.1:4180; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Uri $request_uri; + # nginx auth_request includes headers but not body + proxy_set_header Content-Length ""; + proxy_pass_request_body off; + } + + location / { + auth_request /oauth2/auth; + error_page 401 =403 /oauth2/sign_in; + + # pass information via X-User and X-Email headers to backend, + # requires running with --set-xauthrequest flag + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $email $upstream_http_x_auth_request_email; + proxy_set_header X-User $user; + proxy_set_header X-Email $email; + + # if you enabled --pass-access-token, this will pass the token to the backend + auth_request_set $token $upstream_http_x_auth_request_access_token; + proxy_set_header X-Access-Token $token; + + # if you enabled --cookie-refresh, this is needed for it to work with auth_request + auth_request_set $auth_cookie $upstream_http_set_cookie; + add_header Set-Cookie $auth_cookie; + + # When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb + # limit and so the OAuth2 Proxy splits these into multiple parts. + # Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response, + # so if your cookies are larger than 4kb, you will need to extract additional cookies manually. + auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1; + + # Extract the Cookie attributes from the first Set-Cookie header and append them + # to the second part ($upstream_cookie_* variables only contain the raw cookie content) + if ($auth_cookie ~* "(; .*)") { + set $auth_cookie_name_0 $auth_cookie; + set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1"; + } + + # Send both Set-Cookie headers now if there was a second part + if ($auth_cookie_name_upstream_1) { + add_header Set-Cookie $auth_cookie_name_0; + add_header Set-Cookie $auth_cookie_name_1; + } + + proxy_pass http://backend/; + # or "root /path/to/site;" or "fastcgi_pass ..." etc + } +} +``` + +When you use ingress-nginx in Kubernetes, you can configure the same behavior with the following annotations on your Ingress resource: + +```yaml +nginx.ingress.kubernetes.io/auth-url: "https:///oauth2/auth" +nginx.ingress.kubernetes.io/auth-signin: "https:///oauth2/start?rd=$escaped_request_uri" +``` + +This minimal configuration works for standard authentication flows. Lua/cookie handling is only needed for advanced scenarios (e.g., multi-part cookies, custom session logic). See the official ingress-nginx example: https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/. + +It is recommended to use `--session-store-type=redis` when expecting large sessions/OIDC tokens (_e.g._ with MS Azure). + +:::tip Kubernetes Dashboard with Azure Entra ID +For a complete example of integrating oauth2-proxy with Kubernetes Dashboard on AKS using Azure Entra ID, including RBAC configuration and troubleshooting, see the [Kubernetes Dashboard on AKS](../providers/ms_entra_id.md#kubernetes-dashboard-on-aks) section in the Microsoft Entra ID provider documentation. +::: + +You have to substitute *name* with the actual cookie name you configured via --cookie-name parameter. If you don't set a custom cookie name the variable should be "$upstream_cookie__oauth2_proxy_1" instead of "$upstream_cookie_name_1" and the new cookie-name should be "_oauth2_proxy_1=" instead of "name_1=". + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.14.x/configuration/integrations/traefik.md b/docs/versioned_docs/version-7.14.x/configuration/integrations/traefik.md new file mode 100644 index 00000000..e4b64b94 --- /dev/null +++ b/docs/versioned_docs/version-7.14.x/configuration/integrations/traefik.md @@ -0,0 +1,184 @@ +--- +id: traefik +title: Traefik +--- + +Set up OAuth2 Proxy with Traefik v2 using the `ForwardAuth` middleware. Includes examples for both error-based redirects and static upstream configurations. + +**Key features:** +- ForwardAuth middleware integration +- Error middleware for 401 redirects +- Static upstream configuration (202 responses) +- Dynamic file configuration examples + + +## Configuring for use with the Traefik (v2) `ForwardAuth` middleware + +**This option requires `--reverse-proxy` option to be set.** + +### ForwardAuth with 401 errors middleware + +The [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) allows Traefik to authenticate requests via the oauth2-proxy's `/oauth2/auth` endpoint on every request, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the whole request through. For example, on Dynamic File (YAML) Configuration: + +```yaml +http: + routers: + a-service: + rule: "Host(`a-service.example.com`)" + service: a-service-backend + middlewares: + - oauth-errors + - oauth-auth + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + oauth: + rule: "Host(`a-service.example.com`, `oauth.example.com`) && PathPrefix(`/oauth2/`)" + middlewares: + - auth-headers + service: oauth-backend + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + + services: + a-service-backend: + loadBalancer: + servers: + - url: http://172.16.0.2:7555 + oauth-backend: + loadBalancer: + servers: + - url: http://172.16.0.1:4180 + + middlewares: + auth-headers: + headers: + sslRedirect: true + stsSeconds: 315360000 + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + sslHost: example.com + stsIncludeSubdomains: true + stsPreload: true + frameDeny: true + oauth-auth: + forwardAuth: + address: https://oauth.example.com/oauth2/auth + trustForwardHeader: true + oauth-errors: + errors: + status: + - "401-403" + service: oauth-backend + query: "/oauth2/sign_in?rd={url}" +``` + +### ForwardAuth with static upstreams configuration + +Redirect to sign_in functionality provided without the use of `errors` middleware with [Traefik v2 `ForwardAuth` middleware](https://doc.traefik.io/traefik/middlewares/http/forwardauth/) pointing to oauth2-proxy service's `/` endpoint + +**Following options need to be set on `oauth2-proxy`:** +- `--upstream=static://202`: Configures a static response for authenticated sessions +- `--reverse-proxy=true`: Enables the use of `X-Forwarded-*` headers to determine redirects correctly + +```yaml +http: + routers: + a-service-route-1: + rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/`)" + service: a-service-backend + middlewares: + - oauth-auth-redirect # redirects all unauthenticated to oauth2 signin + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + a-service-route-2: + rule: "Host(`a-service.example.com`) && PathPrefix(`/no-auto-redirect`)" + service: a-service-backend + middlewares: + - oauth-auth-wo-redirect # unauthenticated session will return a 401 + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + services-oauth2-route: + rule: "Host(`a-service.example.com`, `b-service.example.com`) && PathPrefix(`/oauth2/`)" + middlewares: + - auth-headers + service: oauth-backend + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + oauth2-proxy-route: + rule: "Host(`oauth.example.com`) && PathPrefix(`/`)" + middlewares: + - auth-headers + service: oauth-backend + tls: + certResolver: default + domains: + - main: "example.com" + sans: + - "*.example.com" + + services: + a-service-backend: + loadBalancer: + servers: + - url: http://172.16.0.2:7555 + b-service-backend: + loadBalancer: + servers: + - url: http://172.16.0.3:7555 + oauth-backend: + loadBalancer: + servers: + - url: http://172.16.0.1:4180 + + middlewares: + auth-headers: + headers: + sslRedirect: true + stsSeconds: 315360000 + browserXssFilter: true + contentTypeNosniff: true + forceSTSHeader: true + sslHost: example.com + stsIncludeSubdomains: true + stsPreload: true + frameDeny: true + oauth-auth-redirect: + forwardAuth: + address: https://oauth.example.com/ + trustForwardHeader: true + authResponseHeaders: + - X-Auth-Request-Access-Token + - Authorization + oauth-auth-wo-redirect: + forwardAuth: + address: https://oauth.example.com/oauth2/auth + trustForwardHeader: true + authResponseHeaders: + - X-Auth-Request-Access-Token + - Authorization +``` + +:::note +If you set up your OAuth2 provider to rotate your client secret, you can use the `client-secret-file` option to reload the secret when it is updated. +::: diff --git a/docs/versioned_docs/version-7.14.x/configuration/overview.md b/docs/versioned_docs/version-7.14.x/configuration/overview.md index b159df09..7bd7bf07 100644 --- a/docs/versioned_docs/version-7.14.x/configuration/overview.md +++ b/docs/versioned_docs/version-7.14.x/configuration/overview.md @@ -83,7 +83,7 @@ Provider specific options can be found on their respective subpages. | flag: `--approval-prompt`
toml: `approval_prompt` | string | OAuth approval_prompt | `"force"` | | flag: `--backend-logout-url`
toml: `backend_logout_url` | string | URL to perform backend logout, if you use `{id_token}` in the url it will be replaced by the actual `id_token` of the user session | | | flag: `--client-id`
toml: `client_id` | string | the OAuth Client ID, e.g. `"123456.apps.googleusercontent.com"` | | -| flag: `--client-secret-file`
toml: `client_secret_file` | string | the file with OAuth Client Secret | | +| flag: `--client-secret-file`
toml: `client_secret_file` | string | the file with OAuth Client Secret. The file must contain the secret only, with no trailing newline | | | flag: `--client-secret`
toml: `client_secret` | string | the OAuth Client Secret | | | flag: `--code-challenge-method`
toml: `code_challenge_method` | string | use PKCE code challenges with the specified method. Either 'plain' or 'S256' (recommended) | | | flag: `--insecure-oidc-allow-unverified-email`
toml: `insecure_oidc_allow_unverified_email` | bool | don't fail if an email address in an id_token is not verified | false | @@ -128,7 +128,7 @@ Provider specific options can be found on their respective subpages. | flag: `--cookie-refresh`
toml: `cookie_refresh` | duration | refresh the cookie after this duration; `0` to disable; not supported by all providers [^1] | | | flag: `--cookie-samesite`
toml: `cookie_samesite` | string | set SameSite cookie attribute (`"lax"`, `"strict"`, `"none"`, or `""`). | `""` | | flag: `--cookie-secret`
toml: `cookie_secret` | string | the seed string for secure cookies (optionally base64 encoded) | | -| flag: `--cookie-secret-file`
toml: `cookie_secret_file` | string | For defining a separate cookie secret file to read the encryption key from | | +| flag: `--cookie-secret-file`
toml: `cookie_secret_file` | string | File containing the cookie secret (must be raw binary, exactly 16, 24, or 32 bytes). Use dd if=/dev/urandom bs=32 count=1 > cookie.secret to generate | | | flag: `--cookie-secure`
toml: `cookie_secure` | bool | set [secure (HTTPS only) cookie flag](https://owasp.org/www-community/controls/SecureFlag) | true | [^1]: The following providers support `--cookie-refresh`: ADFS, Azure, GitLab, Google, Keycloak and all other Identity Providers which support the full [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens) diff --git a/docs/versioned_docs/version-7.14.x/features/endpoints.md b/docs/versioned_docs/version-7.14.x/features/endpoints.md index db00ba1e..5befce18 100644 --- a/docs/versioned_docs/version-7.14.x/features/endpoints.md +++ b/docs/versioned_docs/version-7.14.x/features/endpoints.md @@ -15,7 +15,7 @@ OAuth2 Proxy responds directly to the following endpoints. All other endpoints w - /oauth2/start - a URL that will redirect to start the OAuth cycle - /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url. - /oauth2/userinfo - the URL is used to return user's email from the session in JSON format. -- /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](../configuration/integration#configuring-for-use-with-the-nginx-auth_request-directive) +- /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](../configuration/integrations/nginx) - /oauth2/static/\* - stylesheets and other dependencies used in the sign_in and error pages ### Sign out diff --git a/docs/versioned_sidebars/version-7.13.x-sidebars.json b/docs/versioned_sidebars/version-7.13.x-sidebars.json index debf4491..cc52cf48 100644 --- a/docs/versioned_sidebars/version-7.13.x-sidebars.json +++ b/docs/versioned_sidebars/version-7.13.x-sidebars.json @@ -22,7 +22,21 @@ "collapsed": false, "items": [ "configuration/overview", - "configuration/integration", + { + "type": "category", + "label": "Integration Guides", + "link": { + "type": "doc", + "id": "configuration/integrations/index" + }, + "items": [ + "configuration/integrations/nginx", + "configuration/integrations/traefik", + "configuration/integrations/caddy", + "configuration/integrations/headlamp", + "configuration/integrations/kubernetes-dashboard" + ] + }, { "type": "category", "label": "OAuth Provider Configuration", diff --git a/docs/versioned_sidebars/version-7.14.x-sidebars.json b/docs/versioned_sidebars/version-7.14.x-sidebars.json index debf4491..cc52cf48 100644 --- a/docs/versioned_sidebars/version-7.14.x-sidebars.json +++ b/docs/versioned_sidebars/version-7.14.x-sidebars.json @@ -22,7 +22,21 @@ "collapsed": false, "items": [ "configuration/overview", - "configuration/integration", + { + "type": "category", + "label": "Integration Guides", + "link": { + "type": "doc", + "id": "configuration/integrations/index" + }, + "items": [ + "configuration/integrations/nginx", + "configuration/integrations/traefik", + "configuration/integrations/caddy", + "configuration/integrations/headlamp", + "configuration/integrations/kubernetes-dashboard" + ] + }, { "type": "category", "label": "OAuth Provider Configuration",