import { Handlers } from "$fresh/server.ts"; import { create, getNumericDate } from "https://deno.land/x/djwt@v2.2/mod.ts"; import { oauth2Client } from "@lib/auth.ts"; import { getCookies, setCookie } from "@std/http/cookie"; import { codeChallengeMap } from "./login.ts"; import { GITEA_SERVER, JWT_SECRET, SESSION_DURATION } from "@lib/env.ts"; import { userDB } from "@lib/db.ts"; import { GiteaOauthUser } from "@lib/types.ts"; import { BadRequestError } from "@lib/errors.ts"; export const handler: Handlers = { async GET(request) { if (!JWT_SECRET) { throw new BadRequestError(); } // Exchange the authorization code for an access token const cookies = getCookies(request.headers); const stored = codeChallengeMap.get(cookies["code_challenge"]); if (!stored) { throw new BadRequestError(); } const { codeVerifier, redirect } = stored; const tokens = await oauth2Client.code.getToken(request.url, { codeVerifier, }); // Use the access token to make an authenticated API request const userInfo = `${GITEA_SERVER}/login/oauth/userinfo`; const userResponse = await fetch(userInfo, { headers: { Authorization: `token ${tokens.accessToken}`, }, }); const oauthUser = await userResponse.json() as GiteaOauthUser; const allUsers = await userDB.findAll(); let user = allUsers.find((u) => u.name === oauthUser.name); if (!user) { user = await userDB.create({ createdAt: new Date(), email: oauthUser.email, name: oauthUser.name, }); } const jwt = await create({ alg: "HS512", type: "JWT" }, { id: user.id, name: user.name, exp: getNumericDate(SESSION_DURATION), }, JWT_SECRET); const headers = new Headers({ location: redirect || "/", }); setCookie(headers, { name: "session_cookie", value: jwt, path: "/", maxAge: SESSION_DURATION, httpOnly: false, secure: true, sameSite: "Lax", }); return new Response(null, { headers, status: 302, }); }, };