diff --git a/deployments/@domains/quinn.vip/nginx/prod.conf b/deployments/@domains/quinn.vip/nginx/prod.conf index e334db33..140831f5 100644 --- a/deployments/@domains/quinn.vip/nginx/prod.conf +++ b/deployments/@domains/quinn.vip/nginx/prod.conf @@ -1,7 +1,8 @@ # vip.transquinnftw.com - VIP client portal # -# This is a client-facing PWA. No nginx auth gate — the app handles -# its own token authentication client-side (invitation code in localStorage). +# This is a client-facing PWA. The client portal handles its own token +# authentication client-side (invitation code in localStorage); only the +# operator /admin view is SSO-gated at the edge (auth_request, below). # The /api/v2/vip/* calls go to my.transquinnftw.com/api/v2/ which proxies # to @features/api :3030 (service-token-gated on the API side). # @@ -71,6 +72,27 @@ server { try_files $uri =404; } + # SSO gate for the admin view (mirrors quinn.www). The client portal stays + # token-auth'd client-side; only /admin requires a signed-in operator. + location = /_sso_verify { + internal; + proxy_pass http://127.0.0.1:3025/auth/validate; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header Cookie $http_cookie; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Forwarded-Host $host; + } + location @sso_redirect { + return 302 https://sso.transquinnftw.com/login?redirect=https://vip.transquinnftw.com$request_uri; + } + # Unauth → SSO login; authed → SPA shell (renders the /admin impersonation view). + location ^~ /admin { + auth_request /_sso_verify; + error_page 401 = @sso_redirect; + try_files /index.html =404; + } + # SPA fallback — all paths serve index.html for client-side routing location / { add_header Cache-Control "no-cache, no-store, must-revalidate";