From 46ce942aec0e4badbc6eb0a785041ba7d38e5879 Mon Sep 17 00:00:00 2001 From: Hong Jiarong Date: Wed, 15 Jul 2026 00:52:58 +0800 Subject: [PATCH] fix(admin-web): use org-scoped Feishu OAuth login URL Unscoped GET /auth/feishu is disabled by default. Derive org slug from /admin/org/:slug, ?org=, or the Alpha Silo hostname and redirect to /auth/feishu/:orgSlug so the login button works on tenant domains. --- hub/admin-web/src/lib/session.ts | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/hub/admin-web/src/lib/session.ts b/hub/admin-web/src/lib/session.ts index a219994..00b8fea 100644 --- a/hub/admin-web/src/lib/session.ts +++ b/hub/admin-web/src/lib/session.ts @@ -32,9 +32,36 @@ export async function loadSession(): Promise { } } +/** + * Resolve org slug for org-scoped Feishu OAuth (`GET /auth/feishu/:orgSlug`). + * Unscoped `/auth/feishu` is disabled unless allowLegacyFeishuOAuth is on. + */ +export function resolveLoginOrgSlug(): string | null { + const path = window.location.pathname.split('/').filter(Boolean); + if (path[0] === 'admin' && path[1] === 'org' && path[2]) { + return decodeURIComponent(path[2]); + } + const q = new URLSearchParams(window.location.search).get('org'); + if (q && q.trim() !== '') return q.trim(); + + // Alpha Silo public host: .educraft.paradigm-edu.net (or educraft-dev) + const host = window.location.hostname.toLowerCase(); + const m = host.match(/^([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)\.educraft(?:-dev)?\./); + if (m?.[1]) return m[1]; + return null; +} + export function redirectToLogin(): void { - const ret = encodeURIComponent(window.location.pathname + window.location.hash); - window.location.href = `/auth/feishu?returnTo=${ret}`; + const ret = encodeURIComponent( + window.location.pathname + window.location.search + window.location.hash, + ); + const slug = resolveLoginOrgSlug(); + if (slug === null) { + // Need an org slug for scoped OAuth — backend login helper can prompt. + window.location.href = `/admin/login?returnTo=${ret}`; + return; + } + window.location.href = `/auth/feishu/${encodeURIComponent(slug)}?returnTo=${ret}`; } export async function logout(): Promise {