import type { NextAuthOptions } from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import bcrypt from "bcryptjs"; import { z } from "zod"; import { normalizeApprovalPermissions } from "@/lib/domain"; import prisma from "@/lib/prisma"; const credentialsSchema = z.object({ identifier: z.string().trim().min(2), password: z.string().min(6) }); export const authOptions: NextAuthOptions = { session: { strategy: "jwt" }, pages: { signIn: "/login" }, providers: [ CredentialsProvider({ name: "Login und Passwort", credentials: { identifier: { label: "Login-Name", type: "text" }, password: { label: "Passwort", type: "password" } }, async authorize(rawCredentials) { const parsedCredentials = credentialsSchema.safeParse(rawCredentials); if (!parsedCredentials.success) { return null; } const normalizedIdentifier = parsedCredentials.data.identifier.toLowerCase(); const matchedUser = await prisma.user.findUnique({ where: { username: normalizedIdentifier } }); if (!matchedUser) { return null; } const isPasswordValid = await bcrypt.compare(parsedCredentials.data.password, matchedUser.passwordHash); if (!isPasswordValid) { return null; } return { id: matchedUser.id, name: matchedUser.username, username: matchedUser.username, email: matchedUser.email, role: matchedUser.role, workingGroupId: matchedUser.workingGroupId, approvalPermissions: normalizeApprovalPermissions( matchedUser.role, matchedUser.approvalPermissions, matchedUser.approvalPreference ) }; } }) ], callbacks: { async jwt({ token, user }) { if (user) { token.id = user.id; token.username = user.username; token.role = user.role; token.workingGroupId = user.workingGroupId; token.approvalPermissions = user.approvalPermissions; } return token; }, async session({ session, token }) { if (session.user) { session.user.id = token.id ?? ""; session.user.username = token.username ?? ""; session.user.role = token.role ?? "MEMBER"; session.user.workingGroupId = token.workingGroupId ?? null; session.user.approvalPermissions = token.approvalPermissions ?? []; } return session; } } };