Forward authentication (Authelia, Authentik)
The forward_auth middleware since v0.1 sends a short request to an
authentication service before each request goes to your backend. The service answers “yes”
with a 2xx status, or answers with anything else, usually a redirect to its login page. This
is how single sign-on portals such as Authelia, Authentik and oauth2-proxy sit in front of apps
that have no login of their own. It works the same way as Traefik’s forwardAuth middleware
(Traefik docs, checked 2026-10-27).
Before you start
Section titled “Before you start”- A running authentication service that ReverseDock can reach, for example
authelia:9091on the same Docker network. - A route for the service’s own login portal, so browsers can reach it.
- HTTPS on the protected routes. Session cookies of the portal should never travel over plain HTTP. See TLS certificates.
How a request is checked
Section titled “How a request is checked”-
ReverseDock sends a
GETtoaddress, with the path and query ofaddress, not of the client’s request. -
The auth request carries the client’s headers (all of them, or only
request_headersplus everyX-Forwarded-*header when that list is set), without connection headers such asConnection,UpgradeandContent-Length. ReverseDock adds what the service needs to know about the original request:Header Value X-Forwarded-MethodThe client’s method. X-Forwarded-Protohttpson a TLS connection, elsehttp.X-Forwarded-HostThe Hostthe client sent, with port if any.X-Forwarded-UriThe path and query, after normalisation. X-Forwarded-ForandX-Real-IPcarry the resolved client IP. -
2xx: the request continues. For each header in
copy_headers, ReverseDock first removes that header from the client’s request, then copies the service’s values. A client cannot send its ownRemote-Userand have it reach the backend. -
Any other status: the service’s answer goes to the client as it is (status, headers and up to 1 MiB of body). A relative
Locationis resolved againstaddress. -
No answer: the request fails closed. It is answered with 504 when the service did not answer within
timeout, and 502 when it could not be reached or its answer was unusable. The backend is never called without a decision.
Example: Authelia
Section titled “Example: Authelia”Authelia documents http://authelia:9091/api/authz/forward-auth as its endpoint and the
Remote-User, Remote-Groups, Remote-Email and Remote-Name headers
(Authelia docs, checked 2026-10-27).
listeners: web: { address: ":80" } websecure: { address: ":443", tls: {} }
certificates: example: cert_file: /etc/rdock/certs/example.pem key_file: /etc/rdock/certs/example.key
routes: auth-portal: match: "Host(`auth.example.com`)" service: authelia wiki: match: "Host(`wiki.example.com`)" service: wiki middlewares: [sso]
services: authelia: backends: [{ address: "authelia:9091" }] wiki: backends: [{ address: "wiki:3000" }]
middlewares: sso: type: forward_auth address: "http://authelia:9091/api/authz/forward-auth" copy_headers: [Remote-User, Remote-Groups, Remote-Email, Remote-Name] timeout: 5sAuthentik and oauth2-proxy work the same way: set address to the endpoint their documentation
gives for Traefik’s forwardAuth, and list the headers it returns in copy_headers.
Settings
Section titled “Settings”| Setting | Default | Meaning |
|---|---|---|
address |
required | http:// or https:// URL of the auth endpoint. |
copy_headers |
none | Response headers of the service copied to the forwarded request. |
request_headers |
all | Client headers sent to the service. X-Forwarded-* headers are always sent. |
timeout |
5s |
Time allowed for the whole exchange with the service. |
trust_forward_header |
false |
Keep X-Forwarded-Method, -Proto, -Host and -Uri already on the request instead of setting them. |
Leave trust_forward_header off unless ReverseDock sits behind another proxy that sets these
headers and is listed in security.trusted_proxies. ReverseDock removes forwarding headers
from untrusted clients before any middleware runs, so even with the setting on, a client on the
internet cannot choose the values.
The auth service’s host name is resolved through DNS and the answer is cached for 10 seconds; connections to it are reused.
Check that it worked
Section titled “Check that it worked”curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' https://wiki.example.com/Without a session, Authelia answers with a redirect to its portal, and curl prints a 3xx
status (or 401) and the portal URL. After you log in in a browser, the wiki opens and its
backend receives Remote-User.
If every request returns 502, ReverseDock cannot reach the service. The application log has a
forward authentication failed warning with the address and the reason.