multimodalart's picture
try to fix cookie stuff
8d67e1c verified
import { NextRequest, NextResponse } from 'next/server';
const TOKEN_ENDPOINT = 'https://huggingface.co/oauth/token';
const USERINFO_ENDPOINT = 'https://huggingface.co/oauth/userinfo';
const STATE_COOKIE = 'hf_oauth_state';
export async function POST(request: NextRequest) {
const clientId = process.env.HF_OAUTH_CLIENT_ID || process.env.NEXT_PUBLIC_HF_OAUTH_CLIENT_ID;
const clientSecret = process.env.HF_OAUTH_CLIENT_SECRET;
if (!clientId || !clientSecret) {
return NextResponse.json({ error: 'OAuth application is not configured' }, { status: 500 });
}
const { code, state } = await request.json().catch(() => ({}));
if (!code) {
return NextResponse.json({ error: 'Authorization code is missing' }, { status: 400 });
}
const storedState = request.cookies.get(STATE_COOKIE)?.value;
if (storedState && state !== storedState) {
const response = NextResponse.json({ error: 'Invalid or expired OAuth state' }, { status: 400 });
response.cookies.delete(STATE_COOKIE);
return response;
}
const origin = request.nextUrl.origin;
const envRedirect =
process.env.HF_OAUTH_REDIRECT_URI || process.env.NEXT_PUBLIC_HF_OAUTH_REDIRECT_URI || '';
const redirectUri = envRedirect.trim() || `${origin}/auth/hf/callback`;
try {
const tokenResponse = await fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
redirect_uri: redirectUri,
client_id: clientId,
client_secret: clientSecret,
}),
});
if (!tokenResponse.ok) {
const errorPayload = await tokenResponse.json().catch(() => ({}));
throw new Error(errorPayload?.error_description || 'Failed to exchange code for token');
}
const tokenData = await tokenResponse.json();
const accessToken = tokenData?.access_token;
if (!accessToken) {
throw new Error('Access token missing in response');
}
const userResponse = await fetch(USERINFO_ENDPOINT, {
headers: { Authorization: `Bearer ${accessToken}` },
});
if (!userResponse.ok) {
throw new Error('Failed to fetch user info');
}
const profile = await userResponse.json();
const namespace = profile?.preferred_username || profile?.name || 'user';
const response = NextResponse.json({
token: accessToken,
namespace,
});
response.cookies.delete(STATE_COOKIE);
return response;
} catch (error: any) {
const response = NextResponse.json({ error: error?.message || 'OAuth flow failed' }, { status: 500 });
response.cookies.delete(STATE_COOKIE);
return response;
}
}