83 lines
1.9 KiB
TypeScript
83 lines
1.9 KiB
TypeScript
// app/api/auth/[...nextauth]/route.ts
|
|
import NextAuth from 'next-auth';
|
|
import CredentialsProvider from 'next-auth/providers/credentials';
|
|
import { PrismaClient } from '@prisma/client';
|
|
import { compare } from 'bcryptjs';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const handler = NextAuth({
|
|
providers: [
|
|
CredentialsProvider({
|
|
name: 'Credentials',
|
|
credentials: {
|
|
email: {
|
|
label: 'Benutzername oder E-Mail',
|
|
type: 'text',
|
|
},
|
|
password: {
|
|
label: 'Passwort',
|
|
type: 'password',
|
|
},
|
|
},
|
|
async authorize(credentials) {
|
|
if (!credentials?.email || !credentials.password) {
|
|
return null;
|
|
}
|
|
|
|
const identifier = credentials.email.trim();
|
|
|
|
// User per E-Mail ODER Benutzername suchen
|
|
const user = await prisma.user.findFirst({
|
|
where: {
|
|
OR: [
|
|
{ email: identifier },
|
|
{ username: identifier },
|
|
],
|
|
},
|
|
});
|
|
|
|
if (!user || !user.passwordHash) {
|
|
return null;
|
|
}
|
|
|
|
const isValid = await compare(credentials.password, user.passwordHash);
|
|
if (!isValid) {
|
|
return null;
|
|
}
|
|
|
|
// Minimal-Userobjekt für NextAuth zurückgeben
|
|
return {
|
|
id: user.id,
|
|
name: user.name ?? user.username ?? user.email,
|
|
email: user.email,
|
|
};
|
|
},
|
|
}),
|
|
],
|
|
pages: {
|
|
signIn: '/login',
|
|
},
|
|
session: {
|
|
strategy: 'jwt',
|
|
},
|
|
callbacks: {
|
|
async jwt({ token, user }) {
|
|
// beim Login User-ID in den Token schreiben
|
|
if (user) {
|
|
token.id = user.id;
|
|
}
|
|
return token;
|
|
},
|
|
async session({ session, token }) {
|
|
// ID aus dem Token wieder in die Session kopieren
|
|
if (session.user && token.id) {
|
|
(session.user as any).id = token.id;
|
|
}
|
|
return session;
|
|
},
|
|
},
|
|
});
|
|
|
|
export { handler as GET, handler as POST };
|