Handoff: Auth Crash on Unauthenticated Access + CORS Blocking Port 6200
Two critical bugs preventing gspace1 testing instance from working: blank page crash when not logged in, and CORS rejecting login requests from port 6200
Handoff: Auth Crash + CORS Blocking on Port 6200
From: Testing Director (Cowork agent) To: Coding agents (Cursor/Claude Code) Priority: Critical — blocks all E2E testing on the gspace1 instance Date: 2026-02-06
Context
We're running two instances of the same repo:
- editor2 on ports 5200/5100/5300 (coding agents) — login works fine
- gspace1 on ports 6200/6100/6300 (testing) — login broken, app crashes
Both share the same backend-api on port 3000. The gspace1 instance is completely unusable for testing.
Bug 1: CORS Blocks Login Requests from Port 6200
Problem
The ALLOWED_ORIGINS env var in .env.local is hardcoded to editor2 workspace ports only. Port 6200 is not included, so the backend rejects all API requests from the gspace1 frontend.
Root Cause
File: .env.local (lines ~66-70)
# CORS Configuration - Allow all workspace frontend ports
ALLOWED_ORIGINS=http://localhost:5200,http://localhost:5100,http://localhost:5300,http://localhost:5400,http://localhost:5500,http://localhost:5010,http://localhost:4200
The comment says "all workspace frontend ports" but only lists editor2 ports. The gspace1 ports (6200, 6100, 6300, 6400, 6500) are missing.
How CORS Resolution Works
File: libs/libs-api/backend-core/src/lib/config/cors.factory.ts
At line ~105-116, getAllowedOrigins() checks if ALLOWED_ORIGINS env var is set. If it is, it overrides the dynamic port-based defaults. Since it's set and doesn't include 6200, requests from port 6200 are rejected.
There IS a localhost fallback at line ~152-156 (isLocalhostOrigin()), but the explicit ALLOWED_ORIGINS takes precedence.
Fix
Option A (Quick): Update .env.local to include gspace1 ports:
ALLOWED_ORIGINS=http://localhost:5200,http://localhost:5100,http://localhost:5300,http://localhost:5400,http://localhost:5500,http://localhost:5010,http://localhost:6200,http://localhost:6100,http://localhost:6300,http://localhost:6400,http://localhost:6500,http://localhost:6010,http://localhost:4200,http://localhost:4301
Option B (Better): Remove the ALLOWED_ORIGINS env var entirely and let the buildDefaultOrigins() function at line ~39-52 dynamically build the list from the port env vars (GOGRAB_SPACE_PORT, etc.). This is what it was designed to do.
Option C (Best): Update cors.factory.ts so the isLocalhostOrigin() fallback (line ~152-156) always allows localhost origins in development, even when ALLOWED_ORIGINS is set. This way any localhost port works during development.
Bug 2: App Crashes (Blank Page) When Not Authenticated
Problem
Navigating to http://localhost:6200/space/chrome-space-1/universe/paks-uni-1/hub without being logged in shows a blank page instead of redirecting to the login page. No error message is shown.
Root Cause Chain
The crash is a cascade of silent failures across 4 layers:
Layer 1: authGuard creates ghost users instead of redirecting
File: libs/libs-ui/auth-ui/src/lib/guards/auth.guard.ts (lines ~57-106)
// ALWAYS generate/get guest user for non-authenticated users
let guestUser = await guestAuth.getMostRecentActiveGuestUser();
if (!guestUser) {
guestUser = await guestAuth.generateTempUser();
}
return true; // ← ALWAYS returns true, never redirects to /login
The guard was designed for "barrier-free" access. It creates a temporary guest user and always allows navigation. This means there's NO mechanism to redirect to login.
Layer 2: spaceGuard swallows errors
File: libs/libs-foundational/core-angular/src/lib/guards/space.guard.ts
At lines ~198-205, when spaceService.initializeSpace() fails for the guest user:
} catch (error) {
console.error('[SpaceGuard] Failed to initialize space:', error);
// Continue - will redirect to landing below if still no space
}
It catches the error, logs it, but returns true anyway (line ~391-393). Navigation continues with no valid space.
Layer 3: spaceResolver returns null
File: libs/libs-foundational/core-angular/src/lib/resolvers/space.resolver.ts (lines ~30-54)
const currentSpace = spaceService.currentSpace();
if (!currentSpace) {
console.warn('[SpaceResolver] No current space available');
return null; // ← Returns null, doesn't redirect or throw
}
Layer 4: Components render with null data → blank page
The route loads successfully (both guards returned true, resolver returned null), but components expect currentSpace to be non-null. They render empty because there's no space context.
Fix
This is an architectural decision. Two approaches:
Option A: Add login redirect (traditional auth)
Modify authGuard to redirect to /login when authService.isAuthenticated() is false, instead of creating guest users. Keep guest user creation as a separate opt-in flow.
Option B: Fix the guest flow (maintain barrier-free design) If the barrier-free design is intentional, fix the guest user + space initialization so it actually works:
spaceGuardshould create a valid temporary space for guest usersspaceResolvershould wait for space init to complete instead of returning null- Add a loading/error state component that shows when space init is in progress or failed
Option C: Add error boundaries (minimum viable fix) At minimum, add a global error handler and error boundary component so the user sees an error message instead of a blank page:
In
app.config.ts, add:{ provide: ErrorHandler, useClass: GlobalErrorHandler }In the main shell component, add a check:
if (!this.spaceService.currentSpace()) { // Show error/redirect to login }In
spaceResolver, redirect to/landingor/logininstead of returning null.
Suggested Approach
I'd recommend Option A + Option C combined: redirect to login when not authenticated AND add error boundaries as a safety net. The guest user creation is a nice feature but it needs a fully working guest space flow to be useful.
Files to Modify
| File | What to Change |
|---|---|
.env.local |
Add gspace1 ports to ALLOWED_ORIGINS (Bug 1 quick fix) |
libs/libs-api/backend-core/src/lib/config/cors.factory.ts |
Make localhost always allowed in dev (Bug 1 proper fix) |
libs/libs-ui/auth-ui/src/lib/guards/auth.guard.ts |
Add login redirect for unauthenticated users (Bug 2) |
libs/libs-foundational/core-angular/src/lib/guards/space.guard.ts |
Return false + redirect when space init fails (Bug 2) |
libs/libs-foundational/core-angular/src/lib/resolvers/space.resolver.ts |
Redirect instead of returning null (Bug 2) |
apps/gograb-space/src/app/app.config.ts |
Add global ErrorHandler (Bug 2 safety net) |
Verification Steps
After the fix, I (Testing Director) will verify:
- Navigate to
http://localhost:6200/login→ login page should render - Enter credentials → login should succeed (no CORS error in network tab)
- After login → should redirect to space dashboard
- Navigate to
http://localhost:6200/space/chrome-space-1/universe/paks-uni-1/hubwhen NOT logged in → should redirect to login (not blank page) - Navigate to
http://localhost:6200/space/chrome-space-1/universe/paks-uni-1/hubwhen logged in → hub should render properly - Check browser console → no unhandled errors
Quick Win (Do This First)
The fastest way to unblock testing is to update .env.local:
- ALLOWED_ORIGINS=http://localhost:5200,http://localhost:5100,http://localhost:5300,http://localhost:5400,http://localhost:5500,http://localhost:5010,http://localhost:4200
+ ALLOWED_ORIGINS=http://localhost:5200,http://localhost:5100,http://localhost:5300,http://localhost:5400,http://localhost:5500,http://localhost:5010,http://localhost:6200,http://localhost:6100,http://localhost:6300,http://localhost:6400,http://localhost:6500,http://localhost:6010,http://localhost:4200,http://localhost:4301
Then restart backend-api so it picks up the new env. This won't fix the blank page crash (Bug 2) but will at least allow login to work if you navigate directly to /login.