Skip to content

Authentik Forward Auth Pattern

This guide documents how to protect any web service with Authentik forward authentication via K8s Ingress.

When to Use This Pattern

Use forward auth when: - App doesn't support native SSO (LDAP/OIDC/SAML) - You want to control WHO can access the app - App runs outside K8s (VMs, Docker, external services)

Note: Forward auth controls access but doesn't provide single sign-on INTO the app. Users authenticate with Authentik, then may still need to log into the app separately.

Architecture

User → app.bogocat.com → K8s Ingress (10.89.97.220)
                 ┌─────────────────────┐
                 │ nginx auth_request  │
                 │ → Authentik server  │
                 └─────────────────────┘
             ┌─────────────┴─────────────┐
             │                           │
      (not authenticated)         (authenticated)
             │                           │
             ▼                           ▼
   Redirect to Authentik         Proxy to backend
   login via /outpost...         (VM, container, etc.)

Prerequisites

  • Authentik deployed in K8s (authentik namespace)
  • Embedded outpost configured (type: proxy)
  • nginx-ingress controller
  • DNS entries pointing to K8s ingress IP

Step-by-Step Setup

Step 1: Create Proxy Provider in Authentik

  1. Go to https://auth.bogocat.com → Providers → Create → Proxy Provider
  2. Configure:
Field Value
Name {app-name}-proxy
Authorization flow default-provider-authorization-implicit-consent
Forward auth mode Forward auth (single application)
External host http://{app-name}.bogocat.com

Step 2: Create Application

  1. Applications → Create
  2. Configure:
Field Value
Name {App Display Name}
Slug {app-name}
Provider {app-name}-proxy
  1. Add Policy Binding → Group → Select allowed group

Step 3: Assign to Embedded Outpost

  1. Applications → Outposts → authentik Embedded Outpost → Edit
  2. Add the new application to Applications
  3. Click Update

Step 4: Create K8s Manifests

Save as /root/tower-fleet/manifests/{namespace}/{app-name}.yaml:

# {App Name} Forward Auth Configuration
# Replace: {app-name}, {APP_NAME}, {NAMESPACE}, {BACKEND_IP}, {PORT}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: {app-name}-auth-headers
  namespace: {NAMESPACE}
data:
  X-Forwarded-Host: "{app-name}.bogocat.com"
  X-Forwarded-Proto: "https"
---
# Backend service (headless + endpoints for external IP)
apiVersion: v1
kind: Service
metadata:
  name: {app-name}-backend
  namespace: {NAMESPACE}
spec:
  type: ClusterIP
  clusterIP: None
  ports:
    - name: http
      port: {PORT}
      targetPort: {PORT}
---
apiVersion: v1
kind: Endpoints
metadata:
  name: {app-name}-backend
  namespace: {NAMESPACE}
subsets:
  - addresses:
      - ip: {BACKEND_IP}
    ports:
      - name: http
        port: {PORT}
---
# ExternalName service to reach Authentik
apiVersion: v1
kind: Service
metadata:
  name: {app-name}-authentik
  namespace: {NAMESPACE}
spec:
  type: ExternalName
  externalName: authentik-server.authentik.svc.cluster.local
---
# Ingress for outpost paths (handles login flow)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {app-name}-outpost
  namespace: {NAMESPACE}
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
    nginx.ingress.kubernetes.io/upstream-vhost: "authentik-server.authentik.svc.cluster.local"
spec:
  ingressClassName: nginx
  rules:
    - host: {app-name}.bogocat.com
      http:
        paths:
          - path: /outpost.goauthentik.io/
            pathType: Prefix
            backend:
              service:
                name: {app-name}-authentik
                port:
                  number: 80
---
# Main ingress with forward auth
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {app-name}
  namespace: {NAMESPACE}
  annotations:
    nginx.ingress.kubernetes.io/auth-url: "http://authentik-server.authentik.svc.cluster.local/outpost.goauthentik.io/auth/nginx"
    nginx.ingress.kubernetes.io/auth-signin: "http://{app-name}.bogocat.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri"
    nginx.ingress.kubernetes.io/auth-response-headers: "Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-uid"
    nginx.ingress.kubernetes.io/auth-proxy-set-headers: "{NAMESPACE}/{app-name}-auth-headers"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  ingressClassName: nginx
  rules:
    - host: {app-name}.bogocat.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {app-name}-backend
                port:
                  number: {PORT}

Step 5: Apply and Add DNS

kubectl apply -f /root/tower-fleet/manifests/{namespace}/{app-name}.yaml

Add DNS in OPNsense: {app-name}.bogocat.com10.89.97.220

Step 6: Test

  1. Open incognito browser
  2. Go to http://{app-name}.bogocat.com
  3. Should redirect to Authentik login
  4. After login → access granted to app

Key Implementation Details

Why Headless Service + Endpoints?

ExternalName services with IP addresses don't work with nginx-ingress (DNS lookup fails). Use headless service pattern instead:

spec:
  type: ClusterIP
  clusterIP: None  # Headless

Why ConfigMap for Headers?

The embedded outpost matches requests by X-Forwarded-Host. nginx-ingress doesn't pass this by default, so we use:

nginx.ingress.kubernetes.io/auth-proxy-set-headers: "{namespace}/{app-name}-auth-headers"

Why Separate Outpost Ingress?

The login flow uses paths like /outpost.goauthentik.io/start and /outpost.goauthentik.io/callback. These must be served under the same hostname as the app (not auth.bogocat.com) so the X-Forwarded-Host header is correct.

Why No configuration-snippet?

The nginx-ingress controller has snippets disabled by admin. Use auth-proxy-set-headers with ConfigMap instead.

Troubleshooting

Issue Cause Fix
404 on auth endpoint App not assigned to outpost Add app to embedded outpost in Authentik
503 Service Unavailable Backend unreachable Check Endpoints exist, verify backend IP reachable
500 Internal Server Error Ingress config error Check ingress controller logs
Redirect loop Cookie issues Clear cookies, check auth-signin URL
"Not Found" on /start Wrong X-Forwarded-Host Verify ConfigMap and auth-proxy-set-headers

Examples

  • arr-stack apps: See arr-stack SSO for Sonarr, Radarr, Jellyseerr, etc.