fix(auth): check cross-subdomain cookie in access gate and dashboard redirects

The access gate and space dashboard redirect scripts checked only
localStorage, which is per-origin. When navigating between subdomains
(e.g. demo → jeff), the session wasn't found. Now both scripts also
check the eid_token cross-subdomain cookie and sync it to localStorage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-24 14:24:30 -07:00
parent 5f25ae02e1
commit 3655632e0f
2 changed files with 52 additions and 15 deletions

View File

@ -339,24 +339,39 @@ export function renderSpaceDashboard(space: string, modules: ModuleInfo[]): stri
import '/shell.js'; import '/shell.js';
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON}); document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
// Check session in localStorage OR cross-subdomain cookie
function _hasSession() {
try {
var raw = localStorage.getItem('encryptid_session');
if (raw && JSON.parse(raw)?.accessToken) return true;
} catch(e) {}
try {
var m = document.cookie.match(/(?:^|; )eid_token=([^;]*)/);
if (!m) return false;
var tok = decodeURIComponent(m[1]);
var parts = tok.split('.');
if (parts.length < 2) return false;
var b64 = parts[1].replace(/-/g,'+').replace(/_/g,'/');
var pad = '='.repeat((4 - b64.length % 4) % 4);
var payload = JSON.parse(atob(b64 + pad));
return payload.exp && Math.floor(Date.now()/1000) < payload.exp;
} catch(e) { return false; }
}
// Logged-in users: redirect to rSpace canvas instead of showing the grid // Logged-in users: redirect to rSpace canvas instead of showing the grid
// Non-demo spaces: redirect logged-out visitors to the main domain landing // Non-demo spaces: redirect logged-out visitors to the main domain landing
try { var loggedIn = _hasSession();
var raw = localStorage.getItem('encryptid_session'); if (loggedIn) {
var loggedIn = raw && JSON.parse(raw)?.accessToken; var dest = window.__rspaceNavUrl
if (loggedIn) { ? window.__rspaceNavUrl('${escapeAttr(space)}', 'rspace')
var dest = window.__rspaceNavUrl : '/${escapeAttr(space)}/rspace';
? window.__rspaceNavUrl('${escapeAttr(space)}', 'rspace') window.location.replace(dest);
: '/${escapeAttr(space)}/rspace'; } else if ('${escapeAttr(space)}' !== 'demo') {
window.location.replace(dest); var host = window.location.host.split(':')[0];
} else if ('${escapeAttr(space)}' !== 'demo') { if (host.endsWith('.rspace.online') || host === 'rspace.online') {
// Don't show other users' space dashboards to logged-out visitors window.location.replace('https://rspace.online/');
var host = window.location.host.split(':')[0];
if (host.endsWith('.rspace.online') || host === 'rspace.online') {
window.location.replace('https://rspace.online/');
}
} }
} catch(e) {} }
// Fix up dashboard links to be subdomain-aware // Fix up dashboard links to be subdomain-aware
if (window.__rspaceNavUrl) { if (window.__rspaceNavUrl) {

View File

@ -627,6 +627,28 @@ export function renderShell(opts: ShellOptions): string {
if (raw) session = JSON.parse(raw); if (raw) session = JSON.parse(raw);
} catch(e) {} } catch(e) {}
// Also check cross-subdomain cookie (localStorage is per-origin)
if (!session || !session.accessToken) {
try {
var m = document.cookie.match(/(?:^|; )eid_token=([^;]*)/);
if (m) {
var tok = decodeURIComponent(m[1]);
var parts = tok.split('.');
if (parts.length >= 2) {
var b64 = parts[1].replace(/-/g,'+').replace(/_/g,'/');
var pad = '='.repeat((4 - b64.length % 4) % 4);
var payload = JSON.parse(atob(b64 + pad));
if (payload.exp && Math.floor(Date.now()/1000) < payload.exp) {
session = { accessToken: tok, claims: payload };
// Sync to localStorage so downstream code sees it
localStorage.setItem('encryptid_session', JSON.stringify(session));
if (payload.username) localStorage.setItem('rspace-username', payload.username);
}
}
}
} catch(e) {}
}
var hasToken = session && session.accessToken; var hasToken = session && session.accessToken;
// Permissioned spaces: only need a valid session // Permissioned spaces: only need a valid session