feat(quinn.vip/nginx): SSO-gate /admin at the edge

Mirror quinn.www's auth_request gate for the VIP app's /admin impersonation
view: unauthenticated requests redirect to sso.transquinnftw.com, authenticated
ones get the SPA shell. The client portal stays token-auth'd client-side; only
/admin requires a signed-in operator. Validates via the local SSO at
127.0.0.1:3025/auth/validate; redirect host is vip.transquinnftw.com.

Takes effect on the next quinn.vip deploy (rsync + nginx reload on vps-0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Natalie 2026-06-25 02:45:18 -04:00
parent 236f0638d0
commit da5222a2ef

View file

@ -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";