(email: string)
| 30 | |
| 31 | /** The real product login, headless: login → hosted AuthKit → callback. */ |
| 32 | const signIn = async (email: string): Promise<string> => { |
| 33 | const login = await fetch(new URL("/api/auth/login", CLOUD_BASE_URL), { redirect: "manual" }); |
| 34 | const stateCookie = cookiePair(login, "wos-login-state"); |
| 35 | const location = login.headers.get("location"); |
| 36 | if (!stateCookie || !location) { |
| 37 | throw new Error(`cloud signIn: login did not redirect to AuthKit (${login.status})`); |
| 38 | } |
| 39 | const authorizeUrl = new URL(location); |
| 40 | if (!authorizeUrl.searchParams.get("state")) { |
| 41 | throw new Error(`cloud signIn: login did not redirect to AuthKit (${login.status})`); |
| 42 | } |
| 43 | // The emulator's hosted login signs in headlessly via login_hint (creating |
| 44 | // the user if new) and redirects back with a code. |
| 45 | authorizeUrl.searchParams.set("login_hint", email); |
| 46 | const consent = await fetch(authorizeUrl, { redirect: "manual" }); |
| 47 | const callbackUrl = consent.headers.get("location"); |
| 48 | if (consent.status !== 302 || !callbackUrl) { |
| 49 | throw new Error(`cloud signIn: AuthKit emulator did not redirect (${consent.status})`); |
| 50 | } |
| 51 | const callback = await fetch(callbackUrl, { |
| 52 | redirect: "manual", |
| 53 | headers: { cookie: stateCookie }, |
| 54 | }); |
| 55 | const session = cookiePair(callback, "wos-session"); |
| 56 | if (!session) throw new Error(`cloud signIn: callback set no session (${callback.status})`); |
| 57 | return session; // "wos-session=<sealed>" |
| 58 | }; |
| 59 | |
| 60 | export const cloudTarget = (): Target => ({ |
| 61 | name: "cloud", |
no test coverage detected