import { error, redirect } from "@sveltejs/kit"; import { discord, type DiscordUser } from "$lib/auth/discord"; import { OAuth2RequestError, type OAuth2Tokens } from "arctic"; import { createSession, generateSessionToken } from "$lib/auth/session"; import { setSessionTokenCookie } from "$lib/auth/cookie"; import { destr } from "destr"; import type { RequestHandler } from "./$types"; import type { CookieData } from "$lib/auth"; export const GET: RequestHandler = async ({ platform, url, cookies, fetch }) => { const db = platform?.env?.TCL_GUESSR_D1 ?? null; if (db === null) error(500, "could not access D1"); const code = url.searchParams.get("code"); const state = url.searchParams.get("state"); const cookie = destr(cookies.get("discord_oauth_state")) ?? null; if (code === null || state === null || cookie === null) { error(400, "missing things from oauth2 response"); } if (state !== cookie.state) { error(400, "state does not match"); } let tokens: OAuth2Tokens; try { tokens = await discord.validateAuthorizationCode(code); } catch (e) { if (e instanceof OAuth2RequestError) { error(400, e.message); } else { error(400, "could not validate auth code"); } } const discordUser: DiscordUser = await fetch("https://discord.com/api/v10/users/@me", { headers: { Authorization: `Bearer ${tokens.accessToken()}`, }, }).then((r) => r.json()); await db .prepare( "INSERT INTO user(id, name, avatar_hash) VALUES (?, ?, ?) ON CONFLICT(id) DO UPDATE SET name=excluded.name, avatar_hash=excluded.avatar_hash;", ) .bind(discordUser.id, discordUser.username, discordUser.avatar) .run(); const sessionToken = generateSessionToken(); const session = await createSession(sessionToken, discordUser.id, db); setSessionTokenCookie(cookies, sessionToken, session.expiresAt); redirect(302, cookie.next); };