assessment-model/src/app/api/auth/[...nextauth]/route.ts
Khalim Conn-Kowlessar 6da2fd1748 removed hard coding
2024-09-10 04:30:04 +01:00

120 lines
3.6 KiB
TypeScript

import NextAuth, { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c";
import { db } from "@/app/db/db";
import { user as userTable, User } from "@/app/db/schema/users";
import { eq } from "drizzle-orm";
const { GOOGLE_CLIENT_ID = "", GOOGLE_CLIENT_SECRET = "" } = process.env;
const {
AZURE_AD_B2C_TENANT_NAME = "",
AZURE_AD_B2C_CLIENT_ID = "",
AZURE_AD_B2C_CLIENT_SECRET = "",
AZURE_AD_B2C_PRIMARY_USER_FLOW = "",
} = process.env;
type OauthProvider = "google";
// TODO: handle token expiration
// https://next-auth.js.org/v3/tutorials/refresh-token-rotation
// propertly set options too
// https://next-auth.js.org/configuration/options
export const AuthOptions: NextAuthOptions = {
providers: [
GoogleProvider({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
authorization: {
params: {
access_type: "offline",
prompt: "consent",
response_type: "code",
},
},
}),
AzureADB2CProvider({
tenantId: AZURE_AD_B2C_TENANT_NAME,
clientId: AZURE_AD_B2C_CLIENT_ID,
clientSecret: AZURE_AD_B2C_CLIENT_SECRET,
primaryUserFlow: AZURE_AD_B2C_PRIMARY_USER_FLOW,
authorization: {
params: {
scope: `https://${process.env.AZURE_AD_B2C_TENANT_NAME}.onmicrosoft.com/api/demo.read https://${process.env.AZURE_AD_B2C_TENANT_NAME}.onmicrosoft.com/api/demo.write offline_access openid`,
prompt: "consent",
},
},
}),
],
pages: {
signIn: "/",
},
callbacks: {
async signIn({ user, account }) {
try {
if (user === null || user.email === null) {
return "/beta";
}
const dbUser: User[] = await db
.select()
.from(userTable)
.where(eq(userTable.email, String(user.email)));
if (dbUser.length > 1) {
console.error(`Multiple users found with email ${user.email}`);
return false;
}
if (dbUser.length === 0 || account === null) {
return "/beta";
}
if (!dbUser[0].oauthId) {
// We make a second query to populate the oauthId and oauthProvider
console.log("Updating user with oauthId and oauthProvider");
const provider = account.provider as OauthProvider;
await db
.update(userTable)
.set({ oauthId: user.id, oauthProvider: provider })
.where(eq(userTable.email, String(user.email)));
console.log("Updated oauthId and oauthProvider");
}
// Set the user's ID from your database
// Because bigint isn't serializable, we need to convert it to a string
user.dbId = dbUser[0].id.toString();
return true;
} catch (error) {
console.error("Error during sign-in: ", error);
return false;
}
},
async jwt({ token, user }) {
// This is executed whenever a JWT is created or refreshed.
// `user` is the object returned from `signIn` callback and
// is only available during sign in, which is why we need to
// store the id in the token and then read it back into the session.
if (user?.dbId) {
token.dbId = user.dbId;
}
return token;
},
async session({ session, token }) {
if (session?.user) {
session.user.dbId = token.dbId;
}
return session;
},
async redirect({ baseUrl }) {
const redirectUrl = baseUrl + "/home";
return redirectUrl;
},
},
};
const handler = NextAuth(AuthOptions);
export { handler as GET, handler as POST };