[grade=B] feat(auth): onboard missing credentials into encrypted vault
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// ===== ENCRYPTED VAULT -> SERVICE SSO HANDOFF =====
|
||||
(function() {
|
||||
function isAllowedReturnUrl(returnUrl, expectedServiceId) {
|
||||
if (!returnUrl || !expectedServiceId || !/^[a-z0-9][a-z0-9-]*$/.test(expectedServiceId)) return false;
|
||||
try {
|
||||
const parsed = new URL(returnUrl, window.location.origin);
|
||||
const suffix = SITE.tld.startsWith('.') ? SITE.tld : `.${SITE.tld}`;
|
||||
const expectedHost = `${expectedServiceId}${suffix}`;
|
||||
return parsed.protocol === 'https:' && parsed.hostname === expectedHost;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildHandoffTarget(returnUrl, token, expectedServiceId) {
|
||||
if (!isAllowedReturnUrl(returnUrl, expectedServiceId)) return null;
|
||||
const parsed = new URL(returnUrl, window.location.origin);
|
||||
if (!token) return null;
|
||||
|
||||
const returnPath = `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
||||
// The shared (dashcaddy_auth) Caddy snippet installs this public landing
|
||||
// route on every protected host. It rewrites to /api/v1/auth/sso-exchange.
|
||||
parsed.pathname = '/dashcaddy-sso';
|
||||
parsed.search = '';
|
||||
parsed.hash = '';
|
||||
parsed.searchParams.set('token', token);
|
||||
parsed.searchParams.set('return', returnPath);
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
async function resume(returnUrl, expectedServiceId, runtime = {}) {
|
||||
if (!isAllowedReturnUrl(returnUrl, expectedServiceId)) return false;
|
||||
const fetchFn = runtime.fetch || window.fetch.bind(window);
|
||||
const locationObj = runtime.location || window.location;
|
||||
try {
|
||||
const response = await fetchFn(`/api/v1/auth/sso-handoff?serviceId=${encodeURIComponent(expectedServiceId)}`, {
|
||||
credentials: 'include',
|
||||
cache: 'no-store',
|
||||
});
|
||||
if (!response.ok) return false;
|
||||
const data = await response.json();
|
||||
const target = data.success && buildHandoffTarget(returnUrl, data.ssoToken, expectedServiceId);
|
||||
if (!target) return false;
|
||||
locationObj.replace(target);
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
window.DCCredentialVault = { isAllowedReturnUrl, buildHandoffTarget, resume };
|
||||
})();
|
||||
Reference in New Issue
Block a user