From 1baef432c460029faca4f013965a87f387af4455 Mon Sep 17 00:00:00 2001 From: Krystie Date: Wed, 8 Jul 2026 21:42:03 -0700 Subject: [PATCH] DC-044: also handle /api/v1/auth/* drift variant in back-compat shim The user's browser cached an older version of the auto-login page that called /dashcaddy-api/api/v1/auth/totp/check-session (with both v1 and auth prefixes) instead of the current /dashcaddy-api/api/auth/totp/check-session (legacy, no v1). The shim only handled the legacy path, so the stale JS 404'd and the page hung at 'Signing in to Plex...' even after the fix was deployed. Add /api/v1/auth/{gate,app-token,totp/check-session} to the shim so stale browser caches keep working. Also add /api/v1/auth/gate and /api/v1/auth/app-token for the same drift reason. --- dashcaddy-api/src/app.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/dashcaddy-api/src/app.js b/dashcaddy-api/src/app.js index b9c8595..966e591 100644 --- a/dashcaddy-api/src/app.js +++ b/dashcaddy-api/src/app.js @@ -193,26 +193,35 @@ async function createApp() { // prefix `/api/auth/...`. The canonical mount is `/api/v1`. Hand-maintained // Caddyfiles have repeatedly drifted back to the old prefix and 404'd the SSO // gate (breaking Plex/Jellyfin/Emby/chat). Transparently rewrite ONLY these - // three auth paths to the v1 mount so the gate is tolerant of that drift. + // auth paths to the v1 mount so the gate is tolerant of that drift. // Must run before configureMiddleware() so CSRF/auth see the canonical path. // This is deliberately narrow — NOT a general `/api` -> `/api/v1` alias. // - // Path mapping (legacy -> canonical): + // Path mapping (any -> canonical): // /api/auth/gate/ -> /api/v1/auth/gate/ (mounted at /auth/gate/:serviceId) + // /api/v1/auth/gate/ -> /api/v1/auth/gate/ (drift, gate pre-1.5.0 sometimes used this) // /api/auth/app-token/ -> /api/v1/auth/app-token/ (mounted at /auth/app-token/:serviceId) + // /api/v1/auth/app-token/ -> /api/v1/auth/app-token/ (drift) // /api/auth/totp/check-session -> /api/v1/totp/check-session (mounted at /totp/check-session — no /auth prefix) + // /api/v1/auth/totp/check-session->/api/v1/totp/check-session (drift) // // The totp case drops `/auth` because the canonical route is /totp/check-session - // (no /auth prefix) but the legacy JS still uses /api/auth/totp/check-session. - // Without this rewrite the JS gets a 404 and the page hangs at + // (no /auth prefix) but the legacy JS still uses /api/auth/totp/check-session + // (and a stale-browser version of the page uses /api/v1/auth/totp/check-session). + // Without these rewrites the JS gets a 404 and the page hangs at // "Signing in to Plex..." forever (user-reported 2026-07-09). app.use((req, res, next) => { - if (req.url.startsWith('/api/auth/gate/') || req.url.startsWith('/api/auth/app-token/')) { + if (req.url.startsWith('/api/auth/gate/') || req.url.startsWith('/api/v1/auth/gate/') + || req.url.startsWith('/api/auth/app-token/') || req.url.startsWith('/api/v1/auth/app-token/')) { req.url = '/api/v1' + req.url.slice(4); // '/api'.length === 4 } else if (req.url.startsWith('/api/auth/totp/check-session')) { // Legacy: /api/auth/totp/check-session -> /api/v1/totp/check-session // Drop both '/api' and '/auth' prefixes (9 chars total). req.url = '/api/v1' + req.url.slice(9); // '/api/auth'.length === 9 + } else if (req.url.startsWith('/api/v1/auth/totp/check-session')) { + // Drift: /api/v1/auth/totp/check-session -> /api/v1/totp/check-session + // Drop the '/api/v1' prefix AND the '/auth' middle segment (13 chars total). + req.url = '/api/v1' + req.url.slice(13); // '/api/v1/auth'.length === 13 } next(); });