[grade=A] fix(auth): preserve cross-host SSO return URLs
Codex: urn:ump:endpmb3rgtqogn2u2jkbbjmsaha6ysjjcxl46fd27ayig5yosawq
This commit is contained in:
+22
-11
@@ -249,20 +249,31 @@
|
||||
// back to window._showTotpOverlay() in `show()` below.
|
||||
window.__dc_049_handled = true;
|
||||
|
||||
function isAllowedReturnUrl(returnUrl) {
|
||||
try {
|
||||
const parsed = new URL(returnUrl, window.location.origin);
|
||||
if (!['http:', 'https:'].includes(parsed.protocol)) return false;
|
||||
if (parsed.origin === window.location.origin) return true;
|
||||
if (parsed.protocol !== 'https:') return false;
|
||||
|
||||
// globals.js is concatenated before this module in core.js, so SITE is
|
||||
// available here. Permit exact hosts and subdomains under the configured
|
||||
// private TLD (for example plex.sami), while rejecting lookalikes such as
|
||||
// plex.sami.evil.example.
|
||||
const suffix = SITE.tld.startsWith('.') ? SITE.tld : `.${SITE.tld}`;
|
||||
return parsed.hostname === suffix.slice(1) || parsed.hostname.endsWith(suffix);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.get('auth') === 'required') {
|
||||
// Save returnUrl the same way totp-auth.js does, so both paths share state.
|
||||
// We don't have access to the SITE constant here (it lives in globals.js's
|
||||
// module scope), so we use a conservative origin-only check. Caddy's
|
||||
// forward_auth already validates the request origin upstream.
|
||||
// Preserve the gated service destination so submitTotpCode() can append
|
||||
// the one-time SSO handoff token and return the browser to that host.
|
||||
const returnUrl = urlParams.get('return');
|
||||
if (returnUrl) {
|
||||
try {
|
||||
const parsed = new URL(returnUrl, window.location.origin);
|
||||
if (parsed.origin === window.location.origin) {
|
||||
try { sessionStorage.setItem('totp_redirect', returnUrl); } catch (_) {}
|
||||
}
|
||||
} catch (_) {}
|
||||
if (returnUrl && isAllowedReturnUrl(returnUrl)) {
|
||||
try { sessionStorage.setItem('totp_redirect', returnUrl); } catch (_) {}
|
||||
}
|
||||
// Clean URL — happens after we've captured the redirect
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
|
||||
Reference in New Issue
Block a user