From c6b30100bdaa659f9f93719e0a55759b5fb4ad36 Mon Sep 17 00:00:00 2001 From: eewing Date: Thu, 19 Feb 2026 09:36:08 -0600 Subject: [PATCH] feat(sso): accept base-issued iframe login Handle Base SSO tokens on initial requests so Stackq can bootstrap PocketBase auth and redirect into the app without a separate login. --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 15 +++++++++++++++ src/hooks.server.ts | 24 ++++++++++++++++++++++++ 3 files changed, 39 insertions(+) delete mode 100644 .DS_Store create mode 100644 .gitignore diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index e3cf853a1c53e32026e2589481f4a19e48a431c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF;5#Y6#fh$ga%cNNHE+0BS=VHil}-;hhRryErcM5n)D))bm?*(*efI^q^g1m zHg*OUVDH}l((l=Z*q0n-LRIA_*`LqvJ-_e1=c0)}3(gtkA z&dd^(tkK+G+T2ZB?SaTJ5flgt{EG_6w_Cy@_R&Ds{eCBAer&kDR+=QWW?JK1<#grt z>(%-F2j5?R(%(Ml?+p{>h^ZKVsEY&iP;;vTledErE(dzgzMW|fxpi7;pGk3)%g5}0 zsFF_yU$BQJy6hM5DX$9NZY^`of=HiVw$(8j6-K)}{}%1>UH?fE7()+o=1*80x53%dA#7OzB?{PVC_PA|0**ssXyw|OV@f)V2%z9nyur+d3 zq2}^_zjiinYkO<>42H*eJoNc4R6OIEEmo--41G`_C=e8QR6zEJh)poIm>JYt2RnTQ zAeK0-jbph>NKRxiwwM{Dho(#_(WEMS#ZY#uQYM}L*v4lDO*)jW%yn#KWp5}-SLb}B z!=Yk>p$`fK1$+fY&Eu4u|7*qfe?KWa1qFfv|CIu&lx!xed?kCf4!oS4wGrDko0!C9 n26YNMdmQV59L3XY+USd9K#VPB2023ue+0A)p$iJUr~-cg!?EiB diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..244db184 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.DS_Store +Thumbs.db + +node_modules +/.svelte-kit +/build +/.output + +.env +.env.* +!.env.example +!.env.test + +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 419403d3..215368bd 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -3,6 +3,7 @@ import PocketBase from "pocketbase"; import type { Handle } from "@sveltejs/kit"; const POCKETBASE_URL = "https://pocketbase.ccllc.pro"; +const BASE_SSO_URL = process.env.BASE_SSO_URL ?? "https://base.ccllc.pro"; const LOGIN_PATH = "/login"; const LOGOUT_PATH = "/logout"; @@ -15,6 +16,29 @@ function isPublicRoute(pathname: string): boolean { } export const handle: Handle = async ({ event, resolve }) => { + // SSO: if opened from Base with ?sso=token, exchange for session and redirect + const ssoParam = event.url.searchParams.get("sso"); + if (ssoParam) { + try { + const res = await fetch( + `${BASE_SSO_URL}/api/sso/exchange?token=${encodeURIComponent(ssoParam)}` + ); + if (res.ok) { + const auth = await res.json(); + const cookieVal = encodeURIComponent( + JSON.stringify({ token: auth.token, model: auth.model }) + ); + const setCookie = `pb_auth=${cookieVal}; Path=/; SameSite=Lax; Max-Age=604800`; + return new Response(null, { + status: 302, + headers: { Location: event.url.pathname, "Set-Cookie": setCookie }, + }); + } + } catch { + // fall through to normal auth + } + } + event.locals.pb = new PocketBase(POCKETBASE_URL); event.locals.pb.authStore.loadFromCookie(event.request.headers.get("cookie") || "");