From d1bbe8ba4520c4afeb40bf90c3380118d90b02fd Mon Sep 17 00:00:00 2001 From: Paul Meier Date: Sun, 21 Jun 2026 15:18:23 -0500 Subject: [PATCH] fix(oidc): redirect callback to /login so the SPA receives oidc_code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a successful OIDC callback the backend redirected the browser to `{frontend_url}/?oidc_code=…` (the site root). But the SvelteKit SPA only reads `oidc_code` on the `/login` route: the root route immediately `goto`s `/files`, and the layout's auth guard bounces an unauthenticated visitor to `/login?redirect=…` — both of which drop the `oidc_code` query param. The exchange step (`POST /api/auth/oidc/exchange`) therefore never runs, so the user lands back on the login form with no session even though the IdP round-trip and callback succeeded. Redirect to `{frontend_url}/login?oidc_code=…` instead — the route that actually performs the exchange. `/login` is public, so the guard doesn't interfere; after a successful exchange the page navigates on to the app. This was masked until now by #510 (the duplicate-callback 403 always fired first); with that fixed, the callback reaches the frontend and this second bug surfaces. Co-Authored-By: Claude Opus 4.8 --- src/interfaces/api/handlers/auth_handler.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/interfaces/api/handlers/auth_handler.rs b/src/interfaces/api/handlers/auth_handler.rs index 64556952..0e760403 100644 --- a/src/interfaces/api/handlers/auth_handler.rs +++ b/src/interfaces/api/handlers/auth_handler.rs @@ -886,8 +886,8 @@ pub async fn oidc_authorize( /// Handle the OIDC provider callback. /// /// Validates the `state` / PKCE / nonce, exchanges the code for tokens, then -/// redirects the browser to the frontend with a short-lived exchange code -/// (`/?oidc_code=…`). +/// redirects the browser to the frontend login route with a short-lived +/// exchange code (`/login?oidc_code=…`), which the SPA swaps for a session. #[utoipa::path( get, path = "/api/auth/oidc/callback", @@ -937,7 +937,7 @@ pub async fn oidc_callback( // Regular web login, redirect to frontend with exchange code let config = auth_app.oidc_config().unwrap(); let frontend_url = config.frontend_url.trim_end_matches('/'); - let redirect_url = format!("{}/?oidc_code={}", frontend_url, exchange_code); + let redirect_url = format!("{}/login?oidc_code={}", frontend_url, exchange_code); tracing::info!("OIDC login successful, redirecting with exchange code"); Ok(Redirect::temporary(&redirect_url)) }