From 01c2de59745f8a493b2ab3e40ce891620ee3c665 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Tue, 16 Jan 2024 09:57:15 +0200 Subject: [PATCH] Improve error checking for NextAuth configuration --- src/app/api/auth/[...nextauth]/route.ts | 100 ++++++++++++++---------- src/types/next-auth.d.ts | 11 ++- 2 files changed, 68 insertions(+), 43 deletions(-) diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 46d1bcf..3c0d9f9 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,28 +1,54 @@ import { NextAuthOptions } from "next-auth"; import NextAuth from "next-auth/next"; import AzureAD from "next-auth/providers/azure-ad"; +import type { Provider } from "next-auth/providers/index"; // import prisma from "@/db/prisma"; +const providers: Provider[] = []; + +const tenantId = process.env.AZURE_AD_TENANT_ID; +if (typeof tenantId !== "string" || !tenantId) { + throw Error( + "Required environment variable `AZURE_AD_TENANT_ID` is not defined", + ); +} + +const clientId = process.env.AZURE_AD_CLIENT_ID; +if (typeof clientId !== "string" || !clientId) { + throw Error( + "Required environment variable `AZURE_AD_CLIENT_ID` is not defined", + ); +} + +const clientSecret = process.env.AZURE_AD_CLIENT_SECRET; +if (typeof clientSecret !== "string" || !clientSecret) { + throw Error( + "Required environment variable `AZURE_AD_CLIENT_SECRET` is not defined", + ); +} + +providers.push( + AzureAD({ + tenantId, + clientId, + clientSecret, + authorization: { + params: {}, + }, + profile(profile) { + return { + id: profile.sub, + azureAdObjectId: profile.oid, + name: profile.name, + email: profile.email, + image: profile.picture ?? null, + }; + }, + }), +); + export const authOptions: NextAuthOptions = { - providers: [ - AzureAD({ - clientId: process.env.AZURE_AD_CLIENT_ID as string, - clientSecret: process.env.AZURE_AD_CLIENT_SECRET as string, - tenantId: process.env.AZURE_AD_TENANT_ID as string, - authorization: { - params: {}, - }, - profile(profile) { - return { - id: profile.sub, - azureAdObjectId: profile.oid, - name: profile.name, - email: profile.email, - image: profile.picture ?? null, - }; - }, - }), - ], + providers, callbacks: { async signIn({ user }) { @@ -37,35 +63,23 @@ export const authOptions: NextAuthOptions = { return true; }, - async jwt({ token, user, account, profile }) { - if (account) { - token.accessToken = account.access_token; - } else { - throw new Error("Access Token was not present in the account"); + jwt({ token, user, account }) { + if (!account) { + throw new Error("Cannot create JWT, received account object is null"); } - if (user) { - token.azureAdObjectId = user.azureAdObjectId; - } else { - throw new Error( - "Azure Active Directory id of was not present in the user", - ); + + if (!account.access_token) { + throw new Error("Access token was not present in account object"); } + token.accessToken = account.access_token; + token.azureAdObjectId = user.azureAdObjectId; + return token; }, session({ session, token }) { - if (token.accessToken && typeof token.accessToken === "string") { - session.accessToken = token.accessToken; - } else { - throw new Error("Access Token was not present in the token"); - } - if (token.azureAdObjectId && typeof token.azureAdObjectId === "string") { - session.user.azureAdObjectId = token.azureAdObjectId; - } else { - throw new Error( - "Azure Active Directory id of was not present in the token", - ); - } + session.accessToken = token.accessToken; + session.user.azureAdObjectId = token.azureAdObjectId; return session; }, @@ -74,5 +88,7 @@ export const authOptions: NextAuthOptions = { signIn: "/auth/signin", }, }; + const handler = NextAuth(authOptions); + export { handler as GET, handler as POST }; diff --git a/src/types/next-auth.d.ts b/src/types/next-auth.d.ts index 3e8a78f..74bc161 100644 --- a/src/types/next-auth.d.ts +++ b/src/types/next-auth.d.ts @@ -1,4 +1,4 @@ -import { DefaultSession, Profile } from "next-auth"; +import { DefaultSession, Profile, JWT } from "next-auth"; declare module "next-auth" { interface Session { @@ -7,8 +7,17 @@ declare module "next-auth" { azureAdObjectId: string; } & DefaultSession["user"]; } + interface User { id: number; azureAdObjectId: string; } } + +declare module "next-auth/jwt" { + /** Returned by the `jwt` callback and `getToken`, when using JWT sessions */ + interface JWT { + accessToken: string; + azureAdObjectId: string; + } +}