Caddy forward_auth directive example with Python code

Caddy Server Authentication


This is a example of how to use the Caddy forward_auth directive to create a separate authentication server.

See and

Important note: The security of this example has not been independently reviewed. Use at your own risk.


This example assumes Caddy v2.5.2 or later.

Use following Caddyfile:

localhost {
    forward_auth localhost:8001 {
        uri /auth/check
        copy_headers X-User X-Forwarded-Uri

    reverse_proxy /auth/* localhost:8001
    reverse_proxy localhost:8002

Start Caddy:

cd ~/GitHub/python3-experiments
./caddy run --config caddy-server-auth/Caddyfile

Start the app server in a separate terminal (port 8002):

cd ~/GitHub/python3-experiments/caddy-server-auth

starting app server
======== Running on ========
(Press CTRL+C to quit)

Start the auth server in another separate terminal — a TEST API token is specified for this example — in a real system the inityial token is auotmatically generated when the server starts (port 8001):

cd ~/GitHub/python3-experiments/caddy-server-auth
python3 api-bfyujsagbtnfvfwjvwfut3hiwy

starting auth server
Authorization: Bearer api-bfyujsagbtnfvfwjvwfut3hiwy
======== Running on ========
(Press CTRL+C to quit)

Use your browser to view a test page — https://localhost/test.

Two TEST users are defined:

And a Service Account with a TEST API token of api-bfyujsagbtnfvfwjvwfut3hiwy.


The Caddyfile has three parts.


The first part uses the route /auth/check to authenticate each request to the proxies that follow. The GET method is used so the body (if present) is not consumed. /auth/check is the verification endpoint.

  1. forward_auth forwards all requests to /auth/check.
  2. The X-User header contains some information about the authenticated user.
  3. The X-Forwarded-Uri header passes the original path to the proxy servers.
    forward_auth localhost:8001 {
        uri /auth/check
        copy_headers X-User X-Forwarded-Uri

Auth server

The second part is a proxy to handle all requests for the /auth route.

    reverse_proxy /auth/* localhost:8001

In this example the auth server has the following additional routes:

  • /auth/password-authenticate — processes the sign-in form and creates the session token and cookie
  • /auth/sign-in — display the sign-in web page
  • /auth/sign-out — removes the session-token and cookie

Application server

The last part of the Caddyfile passes all remaining requests to the application server.

    reverse_proxy localhost:8002

In this example the app server has the following routes:

  • /
  • /admin — authorises users with a role of admin to view the page
  • /test
  • /api-test — returns JSON data for api access

Browser UI

as one of the users shown above.

API (use the api token returned when the server starts)

As well as password users, an API can access the website using the Authorization header.

When the auth server starts, it prints the Authorization which has been automatically generated or specified on the command line.

curl --header "Authorization: Bearer api-bfyujsagbtnfvfwjvwfut3hiwy" https://localhost/api-test
{"result": "ok", "title": "API Test Page"}

curl --header "Authorization: Bearer api-zzz" https://localhost/api-test
401: Unauthorized

curl --header "Authorization: Bearer api-bfyujsagbtnfvfwjvwfut3hiwy" https://localhost/zzz     
404: Not Found


X-Forwarded-For header

If a request goes through multiple proxies (or one proxy multiple times), the addresses of each successive proxy is listed.

The format is:

X-Forwarded-For: <client>, <proxy1>, <proxy2>

more information