import NextAuth, { type DefaultSession } from 'next-auth'; import type { Adapter } from '@auth/core/adapters'; import Credentials from 'next-auth/providers/credentials'; import { PrismaAdapter } from '@auth/prisma-adapter'; import { prisma } from './db'; export const AUTH_ROLE_CLAIM = 'role'; declare module 'next-auth' { interface User { role: string; } interface Session { user: DefaultSession['user'] & { role: string; }; } } export const { handlers, auth, signIn, signOut } = NextAuth({ adapter: PrismaAdapter(prisma) as Adapter, providers: [ Credentials({ name: 'Email', credentials: { email: { label: 'Email', type: 'email', placeholder: 'user@example.com' }, password: { label: 'Password', type: 'password' }, }, authorize: async (credentials) => { const email = String(credentials?.email || '').trim().toLowerCase(); const password = String(credentials?.password || ''); if (!email || !password) return null; const user = await prisma.user.findUnique({ where: { email } }); if (!user) return null; if (user.passwordHash && user.passwordHash !== password) { return null; } return { id: user.id, name: user.name, email: user.email, role: user.role, }; }, }), ], callbacks: { async session({ session, user, token }) { if (user) { session.user = { ...session.user, role: user.role, }; } if (token) { session.user = { ...session.user, role: String(token[AUTH_ROLE_CLAIM] || 'FREE'), }; } return session; }, async jwt({ token, user }) { if (user?.role) { token[AUTH_ROLE_CLAIM] = user.role; } return token; }, }, session: { strategy: 'jwt', maxAge: 60 * 60 * 24 * 14, }, pages: { signIn: '/paywall', }, secret: process.env.NEXTAUTH_SECRET, });