diff --git a/apps/api/src/routes/setup.ts b/apps/api/src/routes/setup.ts index 5869489..3bb470f 100644 --- a/apps/api/src/routes/setup.ts +++ b/apps/api/src/routes/setup.ts @@ -178,4 +178,48 @@ setupRouter.post("/auth-provider", zValidator("json", authProviderBootstrapSchem createdAt: row.createdAt, updatedAt: row.updatedAt, }, 201); -}); \ No newline at end of file +}); + +/** + * POST /api/setup/auth-provider/test + * Unauthenticated endpoint to validate an OIDC provider configuration during OOBE. + * Fetches the OIDC discovery document to confirm the issuer is reachable. + * Only available when needsSetup is true (no super user = fresh install). + */ +setupRouter.post("/auth-provider/test", zValidator("json", authProviderBootstrapSchema), async (c) => { + const db = getDb(); + + // Guard: only allow during fresh install (no super user yet) + const [superUser] = await db + .select({ id: staff.id }) + .from(staff) + .where(eq(staff.isSuperUser, true)) + .limit(1); + + if (superUser) { + return c.json({ ok: false, error: "Setup has already been completed." }, 403); + } + + const body = c.req.valid("json"); + + // Determine the discovery URL + const discoveryUrl = body.internalBaseUrl + ? `${body.internalBaseUrl}/application/o/.well-known/openid-configuration` + : `${body.issuerUrl}/.well-known/openid-configuration`; + + try { + const res = await fetch(discoveryUrl, { method: "GET" }); + if (!res.ok) { + return c.json({ + ok: false, + error: `OIDC discovery failed (HTTP ${res.status}). Check your Issuer URL and Internal Base URL.`, + }); + } + return c.json({ ok: true }); + } catch (e) { + return c.json({ + ok: false, + error: "Could not reach the OIDC provider. Check your Issuer URL and network connectivity.", + }); + } +}); diff --git a/apps/web/src/pages/SetupWizard.jsx b/apps/web/src/pages/SetupWizard.jsx index 2d4de2d..aaaf269 100644 --- a/apps/web/src/pages/SetupWizard.jsx +++ b/apps/web/src/pages/SetupWizard.jsx @@ -82,7 +82,7 @@ export function SetupWizard() { setTestingConnection(true); setTestResult(null); try { - const res = await fetch("/api/admin/auth-provider/test", { + const res = await fetch("/api/setup/auth-provider/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({