diff --git a/infra/deploy/stack/lb/Caddyfile b/infra/deploy/stack/lb/Caddyfile index 46402ef..8ea7ffb 100644 --- a/infra/deploy/stack/lb/Caddyfile +++ b/infra/deploy/stack/lb/Caddyfile @@ -13,6 +13,34 @@ { auto_https off admin off + + # WITHOUT THIS, EVERY OAUTH REDIRECT URI THE BACKEND BUILDS IS http://. + # + # There are two Caddy hops in front of the app: the HOST Caddy terminates TLS + # and sets X-Forwarded-Proto: https, then proxies to 127.0.0.1:8137 over plain + # HTTP; this LB is the second hop. Caddy only preserves an incoming + # X-Forwarded-* header when the immediate peer is a TRUSTED proxy — otherwise + # it overwrites the header with the scheme of the connection it just received, + # which here is http. So the app saw http:// no matter how the user arrived. + # + # accounts/oauth.py:_redirect_uri builds the callback from x-forwarded-proto, + # and that URI must match what is registered in the provider's console. + # Discord tolerates the http:// form; GOOGLE REJECTS a non-HTTPS redirect URI + # for a web client outright, so Google sign-in could not work at all until + # this was fixed — independently of whether the credentials were configured. + # + # Measured on vps2 before the fix, same request to each hop: + # direct to web, XFP=https -> https://thermograph.org/api/v2/... + # through this LB, XFP=https -> http://thermograph.org/api/v2/... + # + # private_ranges covers 127.0.0.1/8 and the Docker bridge ranges, which is + # where the host Caddy reaches this container from. Nothing outside the box + # can connect here — the LB is bound to loopback precisely so it cannot be + # reached un-fronted (hazard #6, above) — so trusting the local peer does not + # widen anything: the only party that can set these headers is the host Caddy. + servers { + trusted_proxies static private_ranges + } } :8137 { diff --git a/infra/deploy/stack/lb/Caddyfile.beta b/infra/deploy/stack/lb/Caddyfile.beta index 756d21d..834f38b 100644 --- a/infra/deploy/stack/lb/Caddyfile.beta +++ b/infra/deploy/stack/lb/Caddyfile.beta @@ -17,6 +17,17 @@ { auto_https off admin off + + # Same reason as ./Caddyfile — see the long note there. Without it this second + # Caddy hop overwrites the host Caddy's X-Forwarded-Proto: https with http, + # and every OAuth redirect URI the backend builds comes out non-HTTPS, which + # Google rejects outright for a web client. + # + # Beta needs it as much as prod does, and arguably first: beta is where an + # OAuth provider change gets tested before it reaches thermograph.org. + servers { + trusted_proxies static private_ranges + } } :8137 {