UNPKG

spacerr

Version:

This starter pack provides a comprehensive Next.js setup, built on top of `create-next-app`, and includes additional features. Developed by spacerrr.

98 lines (84 loc) 3.4 kB
import { createTokenAndSendVeriticationLink } from "@/packages/auth/actions"; import { signInFormSchema } from "@/packages/auth/schemas"; import { db } from "@/packages/database"; import { createAccountAndLinkGoogle, findUserByEmail } from "@/packages/database/actions"; import { PrismaAdapter } from "@auth/prisma-adapter"; import bcrypt from "bcryptjs"; import NextAuth, { AuthError } from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import Google from "next-auth/providers/google"; import type { CustomErrorType, NextAuthErrorType } from "@/lib/error"; export class CustomAuthError extends AuthError { constructor(type: NextAuthErrorType, cause?: { type: CustomErrorType | undefined }) { super(); this.stack = undefined; this.type = type; this.cause = cause; } } export const { handlers, auth, signIn, signOut } = NextAuth({ session: { strategy: "jwt", }, adapter: PrismaAdapter(db), providers: [ Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), CredentialsProvider({ async authorize(credentials) { const { success, data: parsedData } = signInFormSchema.safeParse(credentials); if (!success) throw new CustomAuthError("CredentialsSignin"); const { email, password } = parsedData; const user = await db.user.findFirst({ where: { email } }); if (!user) throw new CustomAuthError("CredentialsSignin"); if (!user.emailVerified) { await createTokenAndSendVeriticationLink(email); throw new CustomAuthError("CredentialsSignin", { type: "EmailVerificationError" }); } const isValidPassword = await bcrypt.compare(password, user.hashedPassword || ""); if (!isValidPassword) throw new CustomAuthError("CredentialsSignin"); return { id: user.id, name: user.name, email: user.email, image: user.image }; }, }), ], callbacks: { async signIn({ user, account, profile }) { try { if (account?.provider === "google") { const email = user.email; if (!email) throw new CustomAuthError("CredentialsSignin"); const existingUser = await findUserByEmail(email); if (!existingUser) { await createAccountAndLinkGoogle( { email, name: user.name || profile?.name || "", image: user.image || profile?.picture, }, { provider: account.provider, providerAccountId: account.providerAccountId, type: account.type || "oauth", refresh_token: account.refresh_token ?? null, access_token: account.access_token ?? null, expires_at: account.expires_at ?? null, token_type: account.token_type ?? null, scope: account.scope ?? null, id_token: account.id_token ?? null, session_state: typeof account.session_state === "string" ? account.session_state : null, }, ); } return true; } return true; } catch (error) { console.error("Error in Google sign-in callback:", error); throw new CustomAuthError("CredentialsSignin"); } }, }, });