Files
vibn-agent-runner/vibn-frontend/app/api/auth/token/route.ts

62 lines
2.1 KiB
TypeScript

/**
* 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 });
}
}