memorium/routes/api/auth/callback.ts

76 lines
2.0 KiB
TypeScript
Raw Normal View History

2023-08-04 22:35:25 +02:00
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 "https://deno.land/std@0.197.0/http/cookie.ts";
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, ctx) {
if (!JWT_SECRET) {
throw new BadRequestError();
}
// Exchange the authorization code for an access token
const cookies = getCookies(request.headers);
const codeVerifier = codeChallengeMap.get(cookies["code_challenge"]);
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: "/",
});
setCookie(headers, {
name: "session_cookie",
value: jwt,
path: "/",
maxAge: SESSION_DURATION,
httpOnly: false,
secure: true,
sameSite: "Lax",
});
return new Response(null, {
headers,
status: 302,
});
},
};