100 lines
2.6 KiB
TypeScript
100 lines
2.6 KiB
TypeScript
import { compare } from 'bcryptjs';
|
|
import { getServerSession, type NextAuthOptions } from 'next-auth';
|
|
import Credentials from 'next-auth/providers/credentials';
|
|
import { getUserByUsername, hasAnyUser } from '@/src/lib/db/user';
|
|
|
|
export const authOptions: NextAuthOptions = {
|
|
providers: [
|
|
Credentials({
|
|
credentials: {
|
|
username: { label: 'Benutzername', type: 'text' },
|
|
password: { label: 'Passwort', type: 'password' },
|
|
},
|
|
async authorize(credentials) {
|
|
if (!credentials?.username || !credentials?.password) {
|
|
return null;
|
|
}
|
|
|
|
const username = credentials.username.trim();
|
|
const password = credentials.password;
|
|
if (process.env.DATABASE_URL) {
|
|
try {
|
|
const dbUser = await getUserByUsername(username);
|
|
|
|
if (dbUser) {
|
|
const isPasswordValid = await compare(password, dbUser.passwordHash);
|
|
if (!isPasswordValid) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: String(dbUser.id),
|
|
name: username,
|
|
email: `${username}@homelab.local`,
|
|
username,
|
|
};
|
|
}
|
|
|
|
if (await hasAnyUser()) {
|
|
return null;
|
|
}
|
|
} catch (error) {
|
|
console.error('Database authentication error:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const adminUsername = process.env.ADMIN_USERNAME || 'admin';
|
|
const adminPasswordHash = process.env.ADMIN_PASSWORD_HASH;
|
|
|
|
if (!adminPasswordHash || username !== adminUsername) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const isPasswordValid = await compare(password, adminPasswordHash);
|
|
|
|
if (!isPasswordValid) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: '1',
|
|
name: 'Admin',
|
|
email: 'admin@homelab.local',
|
|
username: adminUsername,
|
|
};
|
|
} catch (error) {
|
|
console.error('Password comparison error:', error);
|
|
return null;
|
|
}
|
|
},
|
|
}),
|
|
],
|
|
pages: {
|
|
signIn: '/login',
|
|
},
|
|
callbacks: {
|
|
async jwt({ token, user }) {
|
|
if (user && user.username) {
|
|
token.username = user.username;
|
|
}
|
|
return token;
|
|
},
|
|
async session({ session, token }) {
|
|
if (session.user) {
|
|
session.user.username = token.username;
|
|
}
|
|
return session;
|
|
},
|
|
},
|
|
session: {
|
|
strategy: 'jwt',
|
|
maxAge: 24 * 60 * 60,
|
|
},
|
|
secret: process.env.NEXTAUTH_SECRET,
|
|
};
|
|
|
|
export function auth() {
|
|
return getServerSession(authOptions);
|
|
}
|