fix: dedupe IdP auto-redirect and fix CSP/bfcache bug on the SPA shell
- Extract tryAutoRedirectToIdp() on the login page so onMount's redirect guard and the post-setup flow share one check instead of drifting. - Fix a real bug: 304 Not Modified responses carry no Content-Type, so is_html misclassified them and attached the strict headerless CSP, which browsers merge into the cached 200's effective headers and defeat the SPA's hash-based CSP on revalidated repeat visits. - Add Cache-Control: no-store on the SPA shell to opt out of bfcache, preventing a pre-deploy shell (stale inline hydration script + CSP hash) from being resurrected byte-for-byte across the OIDC redirect's full-page navigations. - Add a manual, human-run SSO-only script/env (ports 8090/1081) since the automated oidc.hurl suite keeps password login enabled and never exercises the auto-redirect guard.
This commit is contained in:
@@ -249,6 +249,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Shared by onMount step 4 and onSetup: true + navigates away iff OIDC is
|
||||
// the only login method. Centralised so the guard can't drift between the
|
||||
// two call sites (only the `?error=` loop-guard, checked at onMount time,
|
||||
// doesn't apply post-setup — a freshly created admin can't have bounced
|
||||
// off the IdP yet).
|
||||
function tryAutoRedirectToIdp(): boolean {
|
||||
if (oidc.enabled && oidc.password_login_enabled === false && oidc.authorize_endpoint) {
|
||||
window.location.replace(oidc.authorize_endpoint);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function onSetup(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
setupError = '';
|
||||
@@ -260,10 +273,14 @@
|
||||
busy = true;
|
||||
try {
|
||||
await setupAdmin(setupEmail, setupPassword);
|
||||
setupSuccess = t('auth.admin_success', 'Administrator created. You can now sign in.');
|
||||
setupEmail = setupPassword = setupConfirm = '';
|
||||
// Admin now exists — fold the setup affordance away and return to login.
|
||||
setupAvailable = false;
|
||||
// OIDC-only: the login page would immediately redirect on the next
|
||||
// visit anyway — skip the "you can now sign in" detour and forward
|
||||
// straight to the IdP instead of leaving a dead-end local form.
|
||||
if (tryAutoRedirectToIdp()) return;
|
||||
setupSuccess = t('auth.admin_success', 'Administrator created. You can now sign in.');
|
||||
setTimeout(() => {
|
||||
mode = 'login';
|
||||
setupSuccess = '';
|
||||
@@ -325,14 +342,7 @@
|
||||
|
||||
// 4) Auto-redirect: when OIDC is the only auth method, skip the login page.
|
||||
// Guard against loops: if the IdP returned ?error=, fall through to the UI.
|
||||
if (
|
||||
oidc.enabled &&
|
||||
oidc.password_login_enabled === false &&
|
||||
oidc.authorize_endpoint &&
|
||||
!setupAvailable &&
|
||||
!page.url.searchParams.has('error')
|
||||
) {
|
||||
window.location.replace(oidc.authorize_endpoint);
|
||||
if (!setupAvailable && !page.url.searchParams.has('error') && tryAutoRedirectToIdp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user