[grade=B] fix(auth): generalize cross-host SSO handoff
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled

Codex deployment review: urn:ump:sufisot7ewy33mhjude3ly6wxcjizagt42ywaicwve6qufqdtvbq

Caddy path-order correction: urn:ump:o6apvvpvhynkouii4cl5ghxpprrwtilrg2dejdy2lqsupoktc6tq
This commit is contained in:
Krystie
2026-07-24 16:03:34 -07:00
parent 003b152230
commit 0cc278abf1
6 changed files with 220 additions and 75 deletions
+20 -5
View File
@@ -35,6 +35,24 @@
if (overlay) overlay.classList.remove('show');
}
function buildSsoHandoffTarget(redirect, token) {
const parsed = new URL(redirect, window.location.origin);
if (parsed.origin === window.location.origin) return parsed.toString();
const suffix = SITE.tld.startsWith('.') ? SITE.tld : `.${SITE.tld}`;
const isPrivateHost = parsed.hostname === suffix.slice(1) || parsed.hostname.endsWith(suffix);
if (parsed.protocol !== 'https:' || !isPrivateHost) return null;
if (!token) return parsed.toString();
const returnPath = `${parsed.pathname}${parsed.search}${parsed.hash}`;
parsed.pathname = '/dashcaddy-sso';
parsed.search = '';
parsed.hash = '';
parsed.searchParams.set('token', token);
parsed.searchParams.set('return', returnPath);
return parsed.toString();
}
// Setup digit input UX
const container = document.getElementById('totp-digits');
if (container) {
@@ -98,11 +116,8 @@
// see our session cookie no matter how it's built, so instead we
// hand it a one-time token in the URL; its login page exchanges
// that for its own host-only cookie via /auth/sso-exchange.
let target = redirect;
if (data.ssoToken) {
const sep = redirect.includes('?') ? '&' : '?';
target = redirect + sep + 'dc_token=' + encodeURIComponent(data.ssoToken);
}
const target = buildSsoHandoffTarget(redirect, data.ssoToken);
if (!target) return;
window.location.href = target;
return;
}