Root cause: browsers don't scope cookies by port. With SESSION_DOMAIN= localhost, all three SPAs share cookies. The CookieBearerToken middleware iterated all cookie names and picked the first match, so logging into the organizer app (port 5174) also authenticated the portal (port 5175). Fix: CookieBearerToken now resolves the correct cookie name from the Origin header (same logic as SetAuthCookie trait). It only reads the cookie matching the requesting app — portal origin reads only crewli_portal_token, app origin reads only crewli_app_token, etc. Falls back to first-available cookie when no Origin header is present (server-to-server requests, tests without explicit Origin). Added 3 cross-app isolation tests: - app cookie does NOT authenticate portal requests - portal cookie does NOT authenticate app requests - correct cookie + matching origin = authenticated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.6 KiB
2.6 KiB