File size: 2,806 Bytes
654b283 | 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | import { NextRequest, NextResponse } from "next/server";
import {
createSignupRecord,
exchangeCodeForToken,
fetchUserInfo,
fetchViewer,
getAppUrl,
getOAuthRedirectUri,
storeSignupRecord,
} from "@/lib/huggingface";
import {
clearOAuthCookies,
clearSessionCookie,
readOAuthCookies,
setSessionCookie,
} from "@/lib/session";
export const runtime = "nodejs";
function redirectWithAuthError(request: NextRequest, code: string) {
const response = NextResponse.redirect(new URL(`/?error=${code}`, getAppUrl(request)));
clearOAuthCookies(response);
clearSessionCookie(response);
return response;
}
export async function GET(request: NextRequest) {
const url = new URL(request.url);
const providerError = url.searchParams.get("error");
if (providerError) {
return redirectWithAuthError(
request,
providerError === "access_denied" ? "oauth_denied" : "oauth_failed",
);
}
const code = url.searchParams.get("code");
const returnedState = url.searchParams.get("state");
const { state, verifier } = readOAuthCookies(request);
if (!code || !returnedState || !state || returnedState !== state || !verifier) {
return redirectWithAuthError(request, "oauth_state");
}
try {
const token = await exchangeCodeForToken({
code,
codeVerifier: verifier,
redirectUri: getOAuthRedirectUri(request),
});
const [userInfo, viewer] = await Promise.all([
fetchUserInfo(token.access_token),
fetchViewer(token.access_token),
]);
const session = {
id: userInfo.sub,
username: userInfo.preferred_username || viewer.name,
name: userInfo.name.trim() || viewer.fullname || viewer.name,
email: userInfo.email ?? viewer.email,
emailVerified: userInfo.email_verified ?? viewer.emailVerified,
avatarUrl: userInfo.picture || viewer.avatarUrl,
profileUrl: userInfo.profile || `${process.env.HF_HUB_URL ?? "https://huggingface.co"}/${viewer.name}`,
website: userInfo.website ?? null,
isPro: userInfo.isPro ?? viewer.isPro,
registrationComplete: false,
};
try {
await storeSignupRecord(createSignupRecord({ session }));
const response = NextResponse.redirect(new URL("/?signed_up=1", getAppUrl(request)));
clearOAuthCookies(response);
setSessionCookie(response, {
...session,
registrationComplete: true,
});
return response;
} catch (error) {
console.error(error);
const response = NextResponse.redirect(new URL("/?error=signup_store", getAppUrl(request)));
clearOAuthCookies(response);
setSessionCookie(response, session);
return response;
}
} catch (error) {
console.error(error);
return redirectWithAuthError(request, "oauth_exchange");
}
}
|