feat(oidc): reduce amount of page when auto_redirect_to_oidc
This commit is contained in:
@@ -99,6 +99,20 @@ export interface OidcProviders {
|
||||
*/
|
||||
require_verified_email?: boolean;
|
||||
authorize_endpoint?: string;
|
||||
/**
|
||||
* Server-computed: true when the `auto_redirect_if_standalone_oidc`
|
||||
* policy is on AND OIDC is the only working method (see
|
||||
* `AuthApplicationService::auto_redirect_to_oidc`). When true the root
|
||||
* layout guard `window.location.replace`s to `authorize_endpoint`
|
||||
* instead of routing through `/login` — the server-side `/login`
|
||||
* middleware only fires on full HTTP loads, so SPA client-side
|
||||
* navigation to `/login` (root guard, dev via Vite) would otherwise
|
||||
* stall on the login page. Because the flag is gated by the admin's
|
||||
* policy on the SERVER, using it on the client does NOT override the
|
||||
* policy toggle — we're just enacting the same decision on paths the
|
||||
* middleware can't reach.
|
||||
*/
|
||||
auto_redirect_to_oidc?: boolean;
|
||||
}
|
||||
|
||||
/** Public OIDC provider info for the login page. */
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user