feat(oidc): reduce amount of page when auto_redirect_to_oidc

This commit is contained in:
Edouard Vanbelle
2026-08-03 23:00:15 +02:00
parent d065f99952
commit 95104904c4
2 changed files with 37 additions and 3 deletions
+23 -3
View File
@@ -12,6 +12,7 @@
import { ui } from '$lib/stores/ui.svelte';
import { hashUrlToPath } from '$lib/utils/hashRedirect';
import { killLegacyServiceWorker } from '$lib/utils/killLegacyServiceWorker';
import { getOidcProviders, type OidcProviders } from '$lib/api/endpoints/auth';
let { children } = $props();
@@ -34,6 +35,14 @@
}
let ready = $state(false);
// Providers info fetched at boot so the guard below can enact the
// SSO-only server-side policy (`auto_redirect_if_standalone_oidc`) on
// SPA client-nav paths the middleware in interfaces/web/mod.rs can't
// see. The middleware only fires on full HTTP loads to /login; when
// the layout guard is about to `goto('/login')` we short-circuit to
// the IdP directly if the server tells us to. Null until fetched;
// the guard waits for it before deciding.
let providers = $state<OidcProviders | null>(null);
onMount(async () => {
await killLegacyServiceWorker();
@@ -51,7 +60,9 @@
const mapped = hashUrlToPath(location.hash);
if (mapped) await goto(resolve(mapped as Pathname), { replaceState: true });
}
await session.load();
// Parallel — providers is a public endpoint independent of session state.
const [, prov] = await Promise.all([session.load(), getOidcProviders()]);
providers = prov;
ready = true;
});
@@ -60,9 +71,18 @@
$effect(() => {
if (!ready) return;
const path = page.url.pathname;
if (!session.isAuthenticated && !isPublic(path)) {
void goto(resolve(`/login?redirect=${encodeURIComponent(path)}`), { replaceState: true });
if (session.isAuthenticated || isPublic(path)) return;
// SSO-only auto-redirect: mirror what the server-side /login
// middleware does for direct HTTP loads. Full-page navigation
// (`window.location`) so we hit the OxiCloud backend fresh — that
// endpoint 307s to the IdP with a fresh state + PKCE challenge.
// `goto()` would keep us in the SPA and never leave.
if (providers?.auto_redirect_to_oidc && providers.authorize_endpoint) {
window.location.replace(providers.authorize_endpoint);
return;
}
void goto(resolve(`/login?redirect=${encodeURIComponent(path)}`), { replaceState: true });
});
</script>