feat: integrate authentication and password management features, including bcrypt for hashing and NextAuth for session handling

This commit is contained in:
Julien Froidefond
2025-11-30 08:04:06 +01:00
parent 7cb1d5f433
commit d663fbcbd0
30 changed files with 3287 additions and 4164 deletions

72
lib/auth.ts Normal file
View File

@@ -0,0 +1,72 @@
import { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { authService } from "@/services/auth.service";
// Get secret with fallback for development
const secret = process.env.NEXTAUTH_SECRET || "dev-secret-key-change-in-production";
// Debug: log secret status (remove in production)
if (process.env.NODE_ENV === "development") {
console.log("🔐 NextAuth secret:", process.env.NEXTAUTH_SECRET ? "✅ Loaded from .env.local" : "⚠️ Using fallback");
}
if (!process.env.NEXTAUTH_SECRET && process.env.NODE_ENV === "production") {
throw new Error(
"NEXTAUTH_SECRET is required in production. Please set it in your environment variables."
);
}
export const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
name: "Credentials",
credentials: {
password: { label: "Mot de passe", type: "password" },
},
async authorize(credentials) {
try {
if (!credentials?.password) {
return null;
}
const isValid = await authService.verifyPassword(credentials.password);
if (!isValid) {
return null;
}
// Return a user object (we don't need a real user, just authentication)
return {
id: "admin",
email: "admin@local",
};
} catch (error) {
console.error("Error in authorize:", error);
return null;
}
},
}),
],
pages: {
signIn: "/login",
},
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60, // 30 days
},
callbacks: {
async jwt({ token, user }) {
if (user) {
token.id = user.id;
}
return token;
},
async session({ session, token }) {
if (session.user && token.id) {
session.user.id = token.id;
}
return session;
},
},
secret,
};