diff options
| author | schererleander <leander@schererleander.de> | 2025-07-02 22:17:57 +0200 |
|---|---|---|
| committer | schererleander <leander@schererleander.de> | 2025-07-02 22:17:57 +0200 |
| commit | ab03900adf080da08a0b2a3628fd0dcf0af28420 (patch) | |
| tree | a54ddb49b949929c5c6b4b0bd2b7ca5c504da54d /src/lib/auth.ts | |
| parent | 198f95f079078e60e05d1ea6607ee14f79721a7e (diff) | |
feat: add libraries and utilities
Diffstat (limited to 'src/lib/auth.ts')
| -rw-r--r-- | src/lib/auth.ts | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/lib/auth.ts b/src/lib/auth.ts new file mode 100644 index 0000000..7681009 --- /dev/null +++ b/src/lib/auth.ts @@ -0,0 +1,87 @@ +import NextAuth, { type NextAuthOptions } from "next-auth" +import CredentialsProvider from "next-auth/providers/credentials" +import { MongoDBAdapter } from "@auth/mongodb-adapter" +import { MongoClient } from "mongodb" +import bcrypt from "bcryptjs" +import dbConnect from "./mongodb" +import User from "@/model/User" +import { loginSchema } from "./validation" + +const client = new MongoClient(process.env.MONGODB_URI!) + +export const authOptions: NextAuthOptions = { + adapter: MongoDBAdapter(client), + providers: [ + CredentialsProvider({ + name: "credentials", + credentials: { + email: { label: "Email", type: "email" }, + password: { label: "Password", type: "password" } + }, + async authorize(credentials) { + if (!credentials?.email || !credentials?.password) { + return null + } + + // Validate and sanitize with Zod + const result = loginSchema.safeParse(credentials) + + if (!result.success) { + return null + } + + const { email, password } = result.data + + await dbConnect() + + const user = await User.findOne({ email }) + if (!user) { + return null + } + + const isPasswordValid = await bcrypt.compare(password, user.password) + if (!isPasswordValid) { + return null + } + + return { + id: user._id.toString(), + email: user.email, + name: user.name, + image: user.profileImage?.url || null, + } + } + }) + ], + session: { + strategy: "jwt" as const + }, + callbacks: { + async jwt({ token, user }: { token: any; user: any }) { + if (user) { + token.id = user.id + } + return token + }, + async session({ session, token }: { session: any; token: any }) { + if (token) { + session.user.id = token.id as string + + // Fetch latest user data from database to get current profile image + await dbConnect() + const currentUser = await User.findById(token.id) + if (currentUser) { + session.user.name = currentUser.name + session.user.email = currentUser.email + session.user.image = currentUser.profileImage?.url || null + } + } + return session + }, + }, + pages: { + signIn: "/login", + }, +} + +export default NextAuth(authOptions)
\ No newline at end of file |
