Spaces:
Sleeping
Sleeping
| import type { VercelRequest, VercelResponse } from "@vercel/node"; | |
| import crypto from "crypto"; | |
| const SESSION_TTL_SECONDS = 10 * 60; // 10 minutes | |
| const FORGE_SESSION_SECRET = process.env.FORGE_SESSION_SECRET!; | |
| function signSession(payload: any): string { | |
| const body = Buffer.from(JSON.stringify(payload)).toString("base64url"); | |
| const sig = crypto | |
| .createHmac("sha256", FORGE_SESSION_SECRET) | |
| .update(body) | |
| .digest("base64url"); | |
| return `${body}.${sig}`; | |
| } | |
| export default async function handler(req: VercelRequest, res: VercelResponse) { | |
| if (req.method !== "POST") return res.status(405).end(); | |
| try { | |
| const authResult = req.body; | |
| // For now we trust authResult structure (replace with actual Pi verification): | |
| const pi_uid = authResult.user?.uid; | |
| const username = authResult.user?.username; | |
| if (!pi_uid || !username) { | |
| return res.status(400).json({ error: "Missing user info from Pi." }); | |
| } | |
| // Mint short-lived Forge Session Token | |
| const now = Math.floor(Date.now() / 1000); | |
| const payload = { | |
| pi_uid, | |
| username, | |
| iat: now, | |
| exp: now + SESSION_TTL_SECONDS, | |
| scope: "agent-session" | |
| }; | |
| const session_token = signSession(payload); | |
| return res.status(200).json({ | |
| status: "ok", | |
| session_token | |
| }); | |
| } catch (e: any) { | |
| console.error(e); | |
| return res.status(500).json({ error: "pi_auth_failed", message: e.message }); | |
| } | |
| } |