UNPKG

wcz-layout

Version:

88 lines (87 loc) 3.61 kB
import { i as getAppSession, t as getAccessToken } from "./user-BQiWoQk1.mjs"; import { i as buildUser } from "./utils-DpcYsXTK.mjs"; import { n as getTokenOnBehalfOf, t as getAppToken } from "./msalServer-BHuM63vM.mjs"; //#region src/lib/auth/authHandlers.ts /** * Server-side handlers for the OAuth2 Authorization Code (PKCE) flow. They are * mounted by thin route files (`/auth/login`, `/auth/callback`, `/auth/logout`) * in the consuming app and drive the full server-side Entra login — the browser * never loads an auth library. */ const redirect = (location) => new Response(null, { status: 302, headers: { Location: location } }); /** The OAuth redirect URI, derived from the request origin. */ const resolveRedirectUri = (origin) => `${origin}/auth/callback`; /** Only same-origin paths are allowed, so `returnTo` cannot become an open redirect. */ const sanitizeReturnTo = (value) => value?.startsWith("/") && !value.startsWith("//") ? value : "/"; /** GET /auth/login — start the flow: stash PKCE + state, redirect to Entra. */ async function handleLogin() { const { getRequestUrl } = await import("@tanstack/react-start/server"); const url = getRequestUrl(); const returnTo = sanitizeReturnTo(url.searchParams.get("returnTo")); const { cryptoProvider, buildAuthCodeUrl } = await import("./entra-DbC3aZkF.mjs"); const { verifier, challenge } = await cryptoProvider.generatePkceCodes(); const state = cryptoProvider.createNewGuid(); await (await getAppSession()).update({ pkceVerifier: verifier, state, returnTo }); return redirect(await buildAuthCodeUrl({ redirectUri: resolveRedirectUri(url.origin), state, codeChallenge: challenge })); } /** GET /auth/callback — finish the flow: validate state, exchange code, set session. */ async function handleCallback() { const { getRequestUrl } = await import("@tanstack/react-start/server"); const url = getRequestUrl(); const session = await getAppSession(); const { pkceVerifier, state: expectedState, returnTo = "/" } = session.data; const error = url.searchParams.get("error"); if (error) { await session.clear(); return redirect(`/?auth_error=${encodeURIComponent(error)}`); } const code = url.searchParams.get("code"); const state = url.searchParams.get("state"); if (!code || !state || !pkceVerifier || state !== expectedState) { await session.clear(); return redirect("/?auth_error=invalid_state"); } try { const { exchangeCodeForSession } = await import("./entra-DbC3aZkF.mjs"); const { refreshToken, claims } = await exchangeCodeForSession({ code, redirectUri: resolveRedirectUri(url.origin), codeVerifier: pkceVerifier }); await session.update({ refreshToken, user: buildUser(claims), pkceVerifier: void 0, state: void 0, returnTo: void 0 }); return redirect(returnTo); } catch (error) { const message = error instanceof Error ? error.message : "token_exchange_failed"; console.error("[auth] code exchange failed:", message); await session.clear(); return redirect(`/?auth_error=${encodeURIComponent(message)}`); } } /** GET /auth/logout — clear the local session and sign out of the Entra session. */ async function handleLogout() { const { getRequestUrl } = await import("@tanstack/react-start/server"); const url = getRequestUrl(); await (await getAppSession()).clear(); const { buildLogoutUrl } = await import("./entra-DbC3aZkF.mjs"); return redirect(buildLogoutUrl(`${url.origin}/`)); } //#endregion export { getAccessToken, getAppToken, getTokenOnBehalfOf, handleCallback, handleLogin, handleLogout }; //# sourceMappingURL=auth.mjs.map