Made with ❤️ for the Traefik community
⭐ Star repo
🐛 Report bug
💡 Request feature
This plugin provides forward authentication specifically designed for Authentik, an open-source identity provider. It works as a Traefik middleware and integrates directly with Authentik's proxy outposts to provide authentication and authorization for your services.
Key features:
Every request received by Traefik is checked against Authentik. If a request is authenticated, the proxy forwards user details to the upstream service by attaching a set of headers. These headers are prefixed with X-Authentik-, such as X-Authentik-Username or X-Authentik-Email.
To prevent header spoofing, any X-Authentik-* headers sent by either the upstream or the downstream are removed. Only Authentik is allowed to set these values. These headers are never included in the response to the user.
User sessions are managed using a cookie named like authentik_proxy_<ID>. This cookie is set by Authentik during the login flow and is used to identify the session in later requests. The upstream service must not try to modify this cookie. Any changes made to it will be ignored and overwritten by the plugin.
forwardAuth?Traefik's built-in forwardAuth middleware is flexible, but that also means more setup and more room for mistakes. This plugin is made specifically for Authentik, so there is no need to write custom routes, tweak headers, or fight with cookie issues.
The official Authentik documentation suggests using forwardAuth, but it doesn't mention key caveats related to header spoofing, cookie security, or infrastructure interference. In fact, the example setup shown in the docs can lead to security issues if used as-is.
This plugin handles those problems for you. It removes untrusted headers, protects cookies, and applies consistent logic to all requests. It also adds functionality that would otherwise require multiple middlewares and complex routing logic.
You can even define different auth behaviors for APIs and websites with just a few config lines. It's a faster, safer, and more reliable way to integrate Authentik with Traefik.
nginx endpoint?Authentik provides multiple outpost endpoints. This plugin uses the /outpost.goauthentik.io/auth/nginx one because it gives more control. Unlike the Traefik endpoint, which always returns 302 redirects, this one returns 401 responses, which lets you decide what to do: deny the request, redirect to login or even skip auth entirely for some paths. This puts the decision of how to handle unauthorized requests closer to your app logic.
It also avoids problems caused by proxies, load balancers, or CDNs that often mess with X-Forwarded-* HTTP headers required by the Traefik endpoint. Instead, the nginx endpoint uses an additional X-Original-Uri header, which stays intact across hops. This makes your auth setup more reliable and predictable.
[!IMPORTANT] Authentik still relies on the
X-Forwarded-Hostheader, so make sure it isn't modified by proxies in the request chain. That's still much simpler than managing all the headers required by other approaches.
Add the plugin to your Traefik configuration using the experimental plugins feature:
File
experimental:plugins:authentik-forward:moduleName: "github.com/xabinapal/traefik-authentik-forward-plugin"version: "v1.0.0"
CLI
--experimental.plugins.authentik-forward.modulename=github.com/xabinapal/traefik-authentik-forward-plugin--experimental.plugins.authentik-forward.version=v1.0.0
address: string, required
Base URL of your Authentik server (e.g., https://auth.example.com).
unauthorizedStatusCode: uint, optional, default 401
HTTP status code to return when denying access for request paths matched by unauthorizedPaths.
redirectStatusCode: uint, optional, default 302
HTTP status code to return when redirecting to login for request paths matched by redirectPaths.
skippedPaths: []string, optional, default ["^/.*$"]
List of regex patterns. If the request path matches one of them, the plugin won't ask Authentik for authorization. This list has priority over other priorities.
unauthorizedPaths: []string, optional, default ["^/.*$"]
List of regex patterns. If the request path matches one of them, the plugin denies access using unauthorizedStatusCode. This list has priority over redirectPaths. Longest match wins.
redirectPaths: []string, optional, default []
List of regex patterns. If the request path matches one of them, the plugin redirects to Authentik using redirectStatusCode. Longest match wins.
[!NOTE] Path matching precedence:
- The path is checked against
skippedPaths. If any regex matches, the request is allowed and Authentik is not checked for authorization.X-Authentik-*headers won't be filled in the upstream request.- Both
unauthorizedPathsandredirectPathsare checked. If no regex matches in either list, the request is allowed, but Authentik is checked, and user info will be sent upstream if authenticated.- If both lists contain matching regexes, the longest matching pattern (by string length) wins. If two matching regexes have the same length, the one from
unauthorizedPathstakes precedence.
timeout: string, optional, default 0s
Connection timeout duration for requests to Authentik (e.g., "30s", "1m"). If not specified or equals to 0, no timeout is applied.
tls.ca: string, optional
Path to the CA certificate file for verifying the Authentik server certificate.
tls.cert: string, optional
Path to the client certificate file for mutual TLS authentication to the Authentik server.
tls.key: string, optional
Path to the client private key file for mutual TLS authentication to the Authentik server.
tls.minVersion: uint, optional, default 12
Minimum TLS version to use (10 for TLS 1.0, 11 for TLS 1.1, 12 for TLS 1.2, 13 for TLS 1.3).
tls.maxVersion: uint, optional, default 13
Maximum TLS version to use (10 for TLS 1.0, 11 for TLS 1.1, 12 for TLS 1.2, 13 for TLS 1.3).
tls.insecureSkipVerify: bool, optional, default false
If set, skip TLS certificate verification, not recommended for production.
http:middlewares:my-auth:plugin:authentik-forward:address: https://auth.example.comtimeout: "30s"tls:ca: "/etc/ssl/certs/ca.pem"cert: "/etc/ssl/certs/client.pem"key: "/etc/ssl/private/client.key"minVersion: 12maxVersion: 13insecureSkipVerify: falseunauthorizedStatusCode: 401redirectStatusCode: 302unauthorizedPaths:- "^/api/.*$"- "^/admin/.*$"redirectPaths:- "^/app/.*$"- "^/$"routers:api:rule: Host(`api.example.com`)middlewares:- my-authservice: api-service
Middleware
apiVersion: traefik.containo.us/v1alpha1kind: Middlewaremetadata:name: auth-middlewarespec:plugin:authentik-forward:address: https://auth.example.comtimeout: "30s"tls:ca: "/etc/ssl/certs/ca.pem"cert: "/etc/ssl/certs/client.pem"key: "/etc/ssl/private/client.key"minVersion: 12maxVersion: 13insecureSkipVerify: falseunauthorizedStatusCode: 401redirectStatusCode: 302unauthorizedPaths:- "^/api/.*$"- "^/admin/.*$"redirectPaths:- "^/app/.*$"- "^/$"
IngressRoute
apiVersion: traefik.containo.us/v1alpha1kind: IngressRoutemetadata:name: api-routespec:entryPoints:- websecureroutes:- match: Host(`api.example.com`)kind: Rulemiddlewares:- name: auth-middlewareservices:- name: api-serviceport: 80
Licensed under the Apache License, Version 2.0. See LICENSE for details.