Forward auth
Using forward auth uses your existing reverse proxy to do the proxying, and only uses the authentik outpost to check authentication and authorization.
To use forward auth instead of proxying, you have to change a couple of settings. In the Proxy Provider, make sure to use one of the Forward auth modes.
Single application
Single application mode works for a single application hosted on its dedicated subdomain. This has the advantage that you can still do per-application access policies in authentik.
Domain level
To use forward auth instead of proxying, you have to change a couple of settings. In the Proxy Provider, make sure to use the Forward auth (domain level) mode.
This mode differs from the Forward auth (single application) mode in the following points:
- You don't have to configure an application in authentik for each domain
- Users don't have to authorize multiple times
There are however also some downsides, mainly the fact that you can't restrict individual applications to different users.
The only configuration difference between single application and domain level is the host you specify.
For single application, you'd use the domain which the application is running on, and only /outpost.goauthentik.io is redirected to the outpost.
For domain level, you'd use the same domain as authentik.
example-outpost is used as a placeholder for the outpost name. authentik.company is used as a placeholder for the authentik install. app.company is used as a placeholder for the external domain for the application. outpost.company is used as a placeholder for the outpost. When using the embedded outpost, this can be the same as authentik.company
Nginx
- Standalone nginx
- Ingress
- Nginx Proxy Manager
server {
# SSL and VHost configuration
listen 443 ssl http2;
server_name _;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
# Increase buffer size for large headers
# This is needed only if you get 'upstream sent too big header while reading response
# header from upstream' error when trying to access an application protected by goauthentik
proxy_buffers 8 16k;
proxy_buffer_size 32k;
location / {
# Put your proxy_pass to your application here
# proxy_pass http://localhost:5000;
# authentik-specific config
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
}
# all requests to /outpost.goauthentik.io must be accessible without authentication
location /outpost.goauthentik.io {
proxy_pass http://outpost.company:9000/outpost.goauthentik.io;
# ensure the host of this vserver matches your external URL you've configured
# in authentik
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie $upstream_http_set_cookie;
# required for POST requests to work
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
# Special location for when the /auth endpoint returns a 401,
# redirect to the /start URL which initiates SSO
location @goauthentik_proxy_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$request_uri;
# For domain level, use the below error_page to redirect to your authentik server with the full redirect path
# return 302 https://authentik.company/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri;
}
}
Create a new ingress for the outpost
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: authentik-outpost
spec:
rules:
- host: app.company
http:
paths:
- backend:
# Or, to use an external Outpost, create an ExternalName service and reference that here.
# See https://kubernetes.io/docs/concepts/services-networking/service/#externalname
serviceName: ak-outpost-example-outpost
servicePort: 9000
path: /outpost.goauthentik.io
This ingress handles authentication requests, and the sign-in flow.
Add these annotations to the ingress you want to protect
metadata:
annotations:
# This should be the in-cluster DNS name for the authentik outpost service
# as when the external URL is specified here, nginx will overwrite some crucial headers
nginx.ingress.kubernetes.io/auth-url: |-
http://ak-outpost-example.authentik.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx
# If you're using domain-level auth, use the authentication URL instead of the application URL
nginx.ingress.kubernetes.io/auth-signin: |-
https://app.company/outpost.goauthentik.io/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-response-headers: |-
Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid
nginx.ingress.kubernetes.io/auth-snippet: |
proxy_set_header X-Forwarded-Host $http_host;
For Nginx Proxy Manager you can use this snippet
# Increase buffer size for large headers
# This is needed only if you get 'upstream sent too big header while reading response
# header from upstream' error when trying to access an application protected by goauthentik
proxy_buffers 8 16k;
proxy_buffer_size 32k;
location / {
# Put your proxy_pass to your application here
proxy_pass $forward_scheme://$server:$port;
# authentik-specific config
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
}
# all requests to /outpost.goauthentik.io must be accessible without authentication
location /outpost.goauthentik.io {
proxy_pass http://outpost.company:9000/outpost.goauthentik.io;
# ensure the host of this vserver matches your external URL you've configured
# in authentik
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie $upstream_http_set_cookie;
# required for POST requests to work
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
# Special location for when the /auth endpoint returns a 401,
# redirect to the /start URL which initiates SSO
location @goauthentik_proxy_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$request_uri;
# For domain level, use the below error_page to redirect to your authentik server with the full redirect path
# return 302 https://authentik.company/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri;
}
Traefik
- Standalone traefik
- docker-compose
- Ingress
http:
middlewares:
authentik:
forwardAuth:
address: http://outpost.company:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
routers:
default-router:
rule: "Host(`app.company`)"
middlewares:
- name: authentik
priority: 10
services: # Unchanged
default-router-auth:
match: "Host(`app.company`) && PathPrefix(`/outpost.goauthentik.io/`)"
priority: 15
services: http://outpost.company:9000/outpost.goauthentik.io
version: "3.7"
services:
traefik:
image: traefik:v2.2
container_name: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
command:
- "--api"
- "--providers.docker=true"
- "--providers.docker.exposedByDefault=false"
- "--entrypoints.web.address=:80"
authentik-proxy:
image: ghcr.io/goauthentik/proxy
ports:
- 9000:9000
- 9443:9443
environment:
AUTHENTIK_HOST: https://your-authentik.tld
AUTHENTIK_INSECURE: "false"
AUTHENTIK_TOKEN: token-generated-by-authentik
# Starting with 2021.9, you can optionally set this too
# when authentik_host for internal communication doesn't match the public URL
# AUTHENTIK_HOST_BROWSER: https://external-domain.tld
labels:
traefik.enable: true
traefik.port: 9000
traefik.http.routers.authentik.rule: Host(`app.company`) && PathPrefix(`/outpost.goauthentik.io/`)
# `authentik-proxy` refers to the service name in the compose file.
traefik.http.middlewares.authentik.forwardauth.address: http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: true
traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
restart: unless-stopped
whoami:
image: containous/whoami
labels:
traefik.enable: true
traefik.http.routers.whoami.rule: Host(`app.company`)
traefik.http.routers.whoami.middlewares: authentik@docker
restart: unless-stopped
Create a middleware:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: authentik
spec:
forwardAuth:
address: http://outpost.company:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwt
- X-authentik-meta-jwks
- X-authentik-meta-outpost
- X-authentik-meta-provider
- X-authentik-meta-app
- X-authentik-meta-version
Add the following settings to your IngressRoute
By default traefik does not allow cross-namespace references for middlewares:
See here to enable it.
spec:
routes:
- kind: Rule
match: "Host(`app.company`)"
middlewares:
- name: authentik
namespace: authentik
priority: 10
services: # Unchanged
# This part is only required for single-app setups
- kind: Rule
match: "Host(`app.company`) && PathPrefix(`/outpost.goauthentik.io/`)"
priority: 15
services:
- kind: Service
# Or, to use an external Outpost, create an ExternalName service and reference that here.
# See https://kubernetes.io/docs/concepts/services-networking/service/#externalname
name: ak-outpost-example-outpost
port: 9000
Enovy (Istio)
Requires authentik 2022.6
Support for this is still in preview, please report bugs on GitHub.
- Envoy (Istio)
Set the following settings on the IstioOperator resource:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio
namespace: istio-system
spec:
meshConfig:
extensionProviders:
- name: "authentik"
envoyExtAuthzHttp:
# Replace with <service-name>.<namespace>.svc.cluster.local
service: "ak-outpost-authentik-embedded-outpost.authentik.svc.cluster.local"
port: "9000"
pathPrefix: "/outpost.goauthentik.io/auth/envoy"
headersToDownstreamOnAllow:
- cookie
headersToUpstreamOnAllow:
- set-cookie
- x-authentik-*
includeRequestHeadersInCheck:
- cookie
Afterwards, you can create AuthorizationPolicy resources to protect your applications like this:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authentik-policy
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: CUSTOM
provider:
name: "authentik"
rules:
- to:
- operation:
hosts:
# You can create a single resource and list all Domain names here, or create multiple resources
- "app.company"