Skip to content

Authentik Forward Auth Patterns

Guide for integrating third-party applications with Authentik SSO using forward authentication.


Authentication Pattern Categories

Pattern When to Use Complexity
Native OIDC/OAuth2 App has OIDC support Low - configure in app
Standard Forward Auth App reads X-Remote-User headers Medium - proxy provider
Custom Headers Forward Auth App needs specific headers High - property mappings
No SSO App has no external auth N/A - use app's native auth

Decision Tree

Does the app support OIDC/OAuth2?
├── YES → Use Native OIDC (preferred)
└── NO → Does it support proxy/header auth?
    ├── YES → Does it use standard headers (X-Remote-User)?
    │   ├── YES → Use Standard Forward Auth
    │   └── NO → Use Custom Headers Forward Auth
    └── NO → No SSO available, use native auth

Pattern 1: Native OIDC/OAuth2 (Preferred)

Examples: Grafana, Paperless-ngx, WikiJS, Gitea, Portainer

How it works: App directly communicates with Authentik using OAuth2/OIDC protocol.

Authentik Setup

  1. Create OAuth2/OpenID Provider
  2. Provider type: OAuth2/OpenID Connect
  3. Client type: Confidential
  4. Redirect URIs: https://app.bogocat.com/callback (app-specific)
  5. Signing Key: Select or create
  6. Scopes: openid, profile, email

  7. Create Application

  8. Name: App Name
  9. Slug: app-slug
  10. Provider: Select the OAuth2 provider

  11. Configure App

  12. Client ID: From provider
  13. Client Secret: From provider
  14. Issuer URL: https://auth.bogocat.com/application/o/app-slug/

No Ingress Auth Annotations Needed

Standard ingress without forward auth:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
spec:
  rules:
  - host: app.bogocat.com
    http:
      paths:
      - path: /
        backend:
          service:
            name: app
            port:
              number: 80

Pattern 2: Standard Forward Auth

Examples: Most apps with "trusted proxy" or "remote user" settings

How it works: Authentik intercepts requests, authenticates user, passes standard headers.

Default Headers Sent by Authentik

Header Value
X-authentik-username Username
X-authentik-uid User ID
X-authentik-email Email address
X-authentik-name Display name
X-authentik-groups Comma-separated groups

Many apps also accept these as: - X-Remote-User / Remote-User - X-Forwarded-User - X-Forwarded-Email

Authentik Setup

  1. Create Proxy Provider
  2. Provider type: Proxy Provider
  3. Authorization flow: default-provider-authorization-implicit-consent
  4. Forward auth mode: Forward auth (single application)
  5. External host: https://app.bogocat.com

  6. Create Application

  7. Name: App Name
  8. Slug: app-slug
  9. Provider: Select the proxy provider

  10. Assign to Outpost

  11. Go to Outposts → authentik Embedded Outpost
  12. Add application to the list

Ingress Configuration

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  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: "https://app.bogocat.com/outpost.goauthentik.io/start?rd=https://$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"
spec:
  rules:
  - host: app.bogocat.com

Pattern 3: Custom Headers Forward Auth

Examples: OtterWiki (x-otterwiki-*), legacy apps with non-standard headers

How it works: Authentik sends default headers, property mappings translate to app-specific headers.

Step 1: Create Property Mapping

In Authentik → Customization → Property Mappings → Create → Scope Mapping

Name: otterwiki-headers

Scope name: otterwiki

Expression:

return {
    "ak_proxy": {
        "user_attributes": {
            "additionalHeaders": {
                "x-otterwiki-name": request.user.username,
                "x-otterwiki-email": request.user.email,
                "x-otterwiki-permissions": "READ,WRITE,UPLOAD,ADMIN"
            }
        }
    }
}

Step 2: Create Proxy Provider with Mapping

  1. Create Proxy Provider (same as Pattern 2)
  2. In "Advanced protocol settings" → Property mappings
  3. Add the custom scope mapping (otterwiki-headers)

Step 3: Configure App

Configure the app to use proxy header authentication:

env:
- name: AUTH_METHOD
  value: "PROXY_HEADER"

Known Apps Requiring Custom Headers

App Headers Required Mapping Expression
OtterWiki x-otterwiki-name, x-otterwiki-email, x-otterwiki-permissions See above
Apache Guacamole REMOTE_USER {"REMOTE_USER": request.user.username}

Proxy Provider Variables Reference

Required Settings

Setting Value Notes
Name app-proxy Convention: {app}-proxy
Authorization flow default-provider-authorization-implicit-consent Or explicit consent
Forward auth mode Forward auth (single application) For single-domain apps
External host https://app.bogocat.com Must match ingress host

Optional Settings

Setting Default When to Change
Token validity 24 hours Increase for long sessions
Intercept header auth Enabled Disable if app sends own auth headers
Basic auth Disabled Enable for API/CLI access
Property mappings None Add for custom headers

Application Variables Reference

Required Settings

Setting Value Notes
Name App Name Display name
Slug app-slug URL-safe, lowercase
Provider app-proxy Must match provider name

Optional Settings

Setting Default When to Change
Launch URL Auto Override if app has specific entry point
Icon None Upload for app library
Policy bindings None Add for group-based access control

Outpost Assignment

Critical: Apps only work after being assigned to an outpost.

Using Embedded Outpost

  1. Applications → Outposts → authentik Embedded Outpost
  2. Click Edit
  3. In "Applications" multi-select, add your app
  4. Click Update

Verifying Assignment

# Check if outpost knows about the app
curl -s http://auth.internal/outpost.goauthentik.io/auth/nginx \
  -H "Host: app.bogocat.com" | head -5
# Should return 401 (not 404)

Troubleshooting

404 on auth request

  • App not assigned to outpost
  • External host doesn't match ingress hostname

500 Internal Server Error

  • Ingress auth-url can't reach Authentik
  • Check: kubectl get svc -n authentik

Redirect loop

  • External host protocol mismatch (http vs https)
  • X-Forwarded-Proto not set correctly

User info not passed to app

  • Check auth-response-headers includes needed headers
  • For custom headers, verify property mapping is assigned to provider