File size: 1,442 Bytes
b98da66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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 });
  }
}