import NextAuth from "next-auth"; import Google from "next-auth/providers/google"; import Facebook from "next-auth/providers/facebook"; import Twitter from "next-auth/providers/twitter"; import Credentials from "next-auth/providers/credentials"; export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ // Google OAuth Google({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, }), // Facebook OAuth Facebook({ clientId: process.env.FACEBOOK_CLIENT_ID!, clientSecret: process.env.FACEBOOK_CLIENT_SECRET!, }), // Twitter OAuth Twitter({ clientId: process.env.TWITTER_CLIENT_ID!, clientSecret: process.env.TWITTER_CLIENT_SECRET!, }), // Email/Password (Credentials) Credentials({ name: "credentials", credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { const res = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: credentials?.email, password: credentials?.password, }), } ); const data = await res.json(); if (res.ok && data.success) { return { id: data.data.user.id, email: data.data.user.email, name: `${data.data.user.firstName || ""} ${data.data.user.lastName || ""}`.trim(), role: data.data.user.role, accessToken: data.data.accessToken, refreshToken: data.data.refreshToken, }; } // Throw the actual error message from the backend throw new Error(data.message || "Invalid email or password"); }, }), ], pages: { signIn: "/login", error: "/login", }, callbacks: { async signIn({ user, account }) { // For OAuth providers, sync with backend if (account?.provider === "google" || account?.provider === "facebook" || account?.provider === "twitter") { try { const res = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/auth/social`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ provider: account.provider, providerId: account.providerAccountId, email: user.email, name: user.name, avatar: user.image, }), } ); const data = await res.json(); if (res.ok && data.success) { (user as any).id = data.data.user.id; (user as any).role = data.data.user.role; (user as any).accessToken = data.data.accessToken; (user as any).refreshToken = data.data.refreshToken; } } catch (error) { console.error("Social auth sync error:", error); } } return true; }, async jwt({ token, user }) { if (user) { token.id = user.id; token.role = (user as any).role; token.accessToken = (user as any).accessToken; token.refreshToken = (user as any).refreshToken; } return token; }, async session({ session, token }) { if (session.user) { (session.user as any).id = token.id; (session.user as any).role = token.role; (session.user as any).accessToken = token.accessToken; (session.user as any).refreshToken = token.refreshToken; } return session; }, }, session: { strategy: "jwt", maxAge: 7 * 24 * 60 * 60, // 7 days }, secret: process.env.NEXTAUTH_SECRET, });