/** * GET /api/auth/token * * Secure endpoint called by the browser during desktop SSO. * Verifies the user has a valid NextAuth browser session, resolves or mints * a Workspace API key, and returns it. */ import { NextResponse } from "next/server"; import { authSession } from "@/lib/auth/session-server"; import { queryOne } from "@/lib/db-postgres"; import { getWorkspaceByOwner } from "@/lib/workspaces"; import { mintWorkspaceApiKey, listWorkspaceApiKeys, revealWorkspaceApiKey } from "@/lib/auth/workspace-auth"; export async function GET() { // 1. Verify caller has an active NextAuth browser session cookie const session = await authSession(); if (!session?.user?.email) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } // 2. Fetch the corresponding Postgres user const user = await queryOne<{ id: string }>( `SELECT id FROM fs_users WHERE data->>'email' = $1 LIMIT 1`, [session.user.email] ); if (!user) { return NextResponse.json({ error: "User not found" }, { status: 401 }); } // 3. Get the user's active workspace const workspace = await getWorkspaceByOwner(user.id); if (!workspace) { return NextResponse.json({ error: "Workspace not found" }, { status: 404 }); } try { // 4. Try to reuse their existing, active workspace API key to avoid key bloating const keys = await listWorkspaceApiKeys(workspace.id); const activeKey = keys.find((k) => !k.revoked_at); if (activeKey) { const revealed = await revealWorkspaceApiKey(workspace.id, activeKey.id); if (revealed) { return NextResponse.json({ token: revealed.token }); } } // 5. Otherwise, mint a fresh key for the desktop client const minted = await mintWorkspaceApiKey({ workspaceId: workspace.id, name: "VibnCode Desktop SSO", createdBy: user.id, }); return NextResponse.json({ token: minted.token }); } catch (err) { console.error("[api/auth/token GET]", err); return NextResponse.json({ error: "Failed to resolve workspace token" }, { status: 500 }); } }