Spaces:
Sleeping
Sleeping
| import { COOKIE_NAME, ONE_YEAR_MS } from "@shared/const"; | |
| import type { Express, Request, Response } from "express"; | |
| import * as db from "../db"; | |
| import { getSessionCookieOptions } from "./cookies"; | |
| import { sdk } from "./sdk"; | |
| function getQueryParam(req: Request, key: string): string | undefined { | |
| const value = req.query[key]; | |
| return typeof value === "string" ? value : undefined; | |
| } | |
| export function registerOAuthRoutes(app: Express) { | |
| app.get("/api/oauth/callback", async (req: Request, res: Response) => { | |
| const code = getQueryParam(req, "code"); | |
| const state = getQueryParam(req, "state"); | |
| if (!code || !state) { | |
| res.status(400).json({ error: "code and state are required" }); | |
| return; | |
| } | |
| try { | |
| const tokenResponse = await sdk.exchangeCodeForToken(code, state); | |
| const userInfo = await sdk.getUserInfo(tokenResponse.accessToken); | |
| if (!userInfo.openId) { | |
| res.status(400).json({ error: "openId missing from user info" }); | |
| return; | |
| } | |
| await db.upsertUser({ | |
| openId: userInfo.openId, | |
| name: userInfo.name || null, | |
| email: userInfo.email ?? null, | |
| loginMethod: userInfo.loginMethod ?? userInfo.platform ?? null, | |
| lastSignedIn: new Date(), | |
| }); | |
| const sessionToken = await sdk.createSessionToken(userInfo.openId, { | |
| name: userInfo.name || "", | |
| expiresInMs: ONE_YEAR_MS, | |
| }); | |
| const cookieOptions = getSessionCookieOptions(req); | |
| res.cookie(COOKIE_NAME, sessionToken, { ...cookieOptions, maxAge: ONE_YEAR_MS }); | |
| res.redirect(302, "/"); | |
| } catch (error) { | |
| console.error("[OAuth] Callback failed", error); | |
| res.status(500).json({ error: "OAuth callback failed" }); | |
| } | |
| }); | |
| } | |