gluestick/src/app/oauth/discord/redirect/route.ts

73 lines
2.1 KiB
TypeScript

import { URLSearchParams } from "url";
import {
discordRedirectUri,
DiscordAccessTokenResponse,
makeTicket,
getDiscordID
} from "../oauth";
import { cookies } from "next/dist/client/components/headers";
import prisma from "@/prisma";
export async function GET(request: Request) {
let url = new URL(request.url);
let code = url.searchParams.get("code");
let state = url.searchParams.get("state");
if (code === null || state === null)
return new Response("missing code/state", { status: 400 });
console.log(`code: ${code}, state: ${state}`);
const cookieStore = cookies();
let cookieState = cookieStore.get("state");
// prevent forgery
console.log(`state: ${state}, cookieState: ${cookieState?.value}`);
if (cookieState?.value !== state)
return new Response("state is invalid", { status: 400 });
let form = new URLSearchParams();
form.append("client_id", process.env.DISCORD_CLIENT_ID);
form.append("client_secret", process.env.DISCORD_CLIENT_SECRET);
form.append("grant_type", "authorization_code");
form.append("code", code);
form.append("redirect_uri", discordRedirectUri());
let tokenResponse = await fetch("https://discord.com/api/oauth2/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: form.toString()
});
if (!tokenResponse.ok) throw "baby";
let tokenBody: DiscordAccessTokenResponse = await tokenResponse.json();
const id = await getDiscordID(tokenBody.access_token);
const user = await prisma.authTicket.create({
data: {
username: null,
ticket: makeTicket(),
discordAuth: {
connectOrCreate: {
where: {
id
},
create: {
id,
accessToken: tokenBody.access_token,
refreshToken: tokenBody.refresh_token,
refreshAt: new Date(Date.now() + tokenBody.expires_in * 1000)
}
}
}
}
});
return new Response(null, {
status: 302,
headers: {
"Set-Cookie": `ticket=${user.ticket}; Path=/;`,
Location: "/register"
}
});
}