aethex-forge/api/auth/exchange-token.ts
sirpiglr 312072a869 Fix various type errors in API files to ensure proper functionality
Resolves TypeScript errors across multiple API files, including Stripe API version mismatches and incorrect type assertions for request data, enabling successful Vercel builds.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c124cc2e-6c8d-4ca4-80d3-5d34ca7aed66
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/qPXTzuE
Replit-Helium-Checkpoint-Created: true
2025-12-08 01:29:26 +00:00

73 lines
2.3 KiB
TypeScript

/**
* Token Exchange Endpoint
*
* Frontend calls this endpoint after receiving the authorization code from Foundation.
* It stores the Foundation's access token and returns user information.
*/
import { VercelRequest, VercelResponse } from "@vercel/node";
const FOUNDATION_URL =
process.env.VITE_FOUNDATION_URL || "https://aethex.foundation";
const API_BASE = process.env.VITE_API_BASE || "https://aethex.dev";
export default async function handler(req: VercelRequest, res: VercelResponse) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const { code } = req.body;
if (!code) {
return res.status(400).json({ error: "Authorization code is required" });
}
try {
// Exchange code for token with Foundation
const tokenResponse = await fetch(`${FOUNDATION_URL}/api/oauth/token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
grant_type: "authorization_code",
code,
client_id: "aethex-corp",
client_secret: process.env.FOUNDATION_OAUTH_CLIENT_SECRET,
redirect_uri: `${API_BASE}/api/auth/foundation-callback`,
}),
});
if (!tokenResponse.ok) {
const errorData = await tokenResponse.json().catch(() => ({}));
console.error("[Exchange Token] Token exchange failed:", errorData);
return res.status(400).json({
error: "Failed to exchange code for token",
details: errorData,
});
}
const tokenData = (await tokenResponse.json()) as { access_token?: string; user?: { id: string } };
if (!tokenData.access_token) {
return res.status(400).json({ error: "No access token in response" });
}
// Set cookie with access token
res.setHeader("Set-Cookie", [
`foundation_access_token=${tokenData.access_token}; Path=/; HttpOnly; Secure; SameSite=Strict`,
`auth_user_id=${tokenData.user?.id || ""}; Path=/; Secure; SameSite=Strict`,
]);
return res.status(200).json({
accessToken: tokenData.access_token,
user: tokenData.user,
});
} catch (error) {
console.error("[Exchange Token] Error:", error);
return res.status(500).json({
error: "Failed to exchange token",
details: String(error),
});
}
}