Loading page...Загружаем страницу...正在加载页面...
AtlasRepo

The Forward-Auth Gate That Verified Perfectly — and Wasn't Live

Description and use

The issue was that Cloudflare Tunnel traffic bypassed the authentik forward‑auth gate, exposing the app to unauthenticated access. Redirecting traffic to the authentik outpost ensured all requests are authenticated.

Problem

A self‑hosted app was protected by an authentik forward‑auth gate, but the gate was only applied to traffic entering via nginx; public traffic routed through a Cloudflare Tunnel bypassed the gate, exposing the app to unauthenticated access.

Outcome

After updating the Cloudflare Tunnel rule, all public traffic to https://app.example.com is routed through authentik’s forward‑auth gate, preventing unauthenticated access to the app.

Workflow

  • 1. Configure authentik proxy provider with external host https://app.example.com and internal host http://app-container:8080.
  • 2. Create an authentik application linked to the proxy provider and the outpost.
  • 3. Point nginx vhost for app.example.com to the authentik outpost.
  • 4. Verify the gate by curling localhost with Host header, confirming 302 redirect and x‑powered‑by: authentik.
  • 5. Discover that public traffic bypasses nginx and hits the Cloudflare Tunnel directly.
  • 6. Inspect Cloudflare Tunnel configuration via API to find the rule app.example.com -> http://app-container:8080.
  • 7. Update the tunnel rule to app.example.com -> http://authentik-server:9000 (the outpost).
  • 8. Test public access again, confirming 302 redirect and x‑powered‑by: authentik.
  • 9. Optionally configure skip_path_regex in the proxy provider to exempt API paths from the gate.

Evidence

I finished the gate, ran the check, and it passed.

Source

An unauthenticated request was being pushed to my authentik login page. Branded, correct, working.

Source

The app answered directly. No login page, no redirect, no gate.

Source

The tunnel’s ingress is a small ordered list evaluated per hostname: app.example.com -> http://app-container:8080 ← straight to the app * -> http_status:404

Source

What finally made it obvious was a response header. The gated check returned x-powered-by: authentik. The public check returned x-powered-by: Express.

Source

  • Record date: 2026-11-02T09:58:47.845Z