forward_auth
An opinionated directive which proxies a clone of the request to an authentication gateway, which can decide whether handling should continue, or needs to be sent to a login page.
Caddy's reverse_proxy
is capable of performing "pre-check requests" to an external service, but this directive is tailored specifically for the authentication usecase. This directive is actually just a convenient way to use a longer, more common configuration (below).
This directive makes a GET
request to the configured upstream with the uri
rewritten:
- If the upstream responds with a
2xx
status code, then access is granted and the header fields incopy_headers
are copied to the original request, and handling continues. - Otherwise, if the upstream responds with any other status code, then the upstream's response is copied back to the client. This response should typically involve a redirect to login page of the authentication gateway.
If this behaviour is not exactly what you want, you may take the expanded form below as a basis and customize it to your needs.
All the subdirectives of reverse_proxy
are supported, and passed through to the underlying reverse_proxy
handler.
Syntax
forward_auth [<matcher>] [<upstreams...>] {
uri <to>
copy_headers <fields...> {
<fields...>
}
}
-
<upstreams...> is a list of upstreams (backends) to which to send auth requests.
-
uri is the URI (path and query) to set on the request sent to the upstream. This will usually be the verification endpoint of the authentication gateway.
-
copy_headers is a list of HTTP header fields to copy from the response to the original request, when the request has a success status code.
The field can be renamed by using
>
followed by the new name, for exampleBefore>After
.A block may be used to list all the fields, one per line, if you prefer for readability.
Since this directive is an opinionated wrapper over a reverse proxy, you can use any of reverse_proxy
's subdirectives to customize it.
Expanded form
The forward_auth
directive is the same as the following configuration. Auth gateways like Authelia work well with this preset. If yours does not, feel free to borrow from this and customize it as needed instead of using the forward_auth
shortcut.
reverse_proxy <upstreams...> {
# Always GET, so that the incoming
# request's body is not consumed
method GET
# Change the URI to the auth gateway's
# verification endpoint
rewrite <to>
# Forward the original method and URI,
# since they get rewritten above; this
# is in addition to other X-Forwarded-*
# headers already set by reverse_proxy
header_up X-Forwarded-Method {method}
header_up X-Forwarded-Uri {uri}
# On a successful response, copy response headers
@good status 2xx
handle_response @good {
# for example, for each copy_headers field...
request_header Remote-User {rp.header.Remote-User}
request_header Remote-Email {rp.header.Remote-Email}
}
}
Examples
Authelia
Delegating authentication to Authelia, before serving your app via a reverse proxy:
# Serve the authentication gateway itself
auth.example.com {
reverse_proxy authelia:9091
}
# Serve your app
app1.example.com {
forward_auth authelia:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy app1:8080
}
For more information, see Authelia's documentation for integrating with Caddy.
Tailscale
Delegating authentication to Tailscale (currently named nginx-auth
, but it still works with Caddy), and using the alternative syntax for copy_headers
to rename the copied headers (note the >
in each header):
forward_auth unix//run/tailscale.nginx-auth.sock {
uri /auth
header_up Remote-Addr {remote_host}
header_up Remote-Port {remote_port}
header_up Original-URI {uri}
copy_headers {
Tailscale-User>X-Webauth-User
Tailscale-Name>X-Webauth-Name
Tailscale-Login>X-Webauth-Login
Tailscale-Tailnet>X-Webauth-Tailnet
Tailscale-Profile-Picture>X-Webauth-Profile-Picture
}
}