如何使用 ldap 和 prisma 使用 next-auth

How to use next-auth using ldap and prisma

我正在使用带有 ldap 的 next-auth 来验证用户名和密码。我能够 log/authenticate 用户使用用户名和密码。但是当我无法使用 prisma 创建用户时,因为在 promise 中不允许等待。 这是我的 [...next-auth].js

`

const ldap = require("ldapjs");
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaClient } from "@prisma/client";

const url = `ldap://${process.env.LDAP_SERVER}`;
const prisma = new PrismaClient();

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "LDAP",
      credentials: {
        username: { label: "DN", type: "text", placeholder: "" },
        password: { label: "Password", type: "password" },
      },
      authorize: async (credentials, req) => {
        // You might want to pull this call out so we're not making a new LDAP client on every login attemp
        const client = ldap.createClient({
          url: url,
        });

        return new Promise((resolve, reject) => {
          client.bind(
            `${credentials.username}@${process.env.LDAP_DOMAIN}`,
            credentials.password,
            (error) => {
              if (error) {
                console.log("Wrong email or password.");
                reject("Wrong email or password.");
              } else {
                console.log("Successfully Logged In");
                resolve({
                  username: credentials.username,
                  password: credentials.password,
                });
              }
              const filter = `(sAMAccountName=${credentials.username})`;

              client.search(
                process.env.LDAP_BASE_DN,
                {
                  filter,
                  scope: "sub",
                  attributes: [
                    "mail",
                    "employeeid",
                    "title",
                    "name",
                    "division",
                    "department",
                    "section",
                  ],
                },
                (err, results) => {
                  if (err) {
                    reject(`User ${username} LDAP search error`);
                  }

                  const entries = [];

                  results.on("searchEntry", (entry) => {
                    entries.push(entry.object);
                  });

                  results.on("error", (err) => {
                    reject("LDAP SEARCH error");
                  });

                  results.on("end", (result) => {
                    if (entries.length == 0) {
                      reject("Something went wrong. Please try again. (AD)");
                    }

                    console.log({ entries });

                    const searchResult = JSON.stringify(entries[0]);
                    const adEmployee = JSON.parse(searchResult);
                    const empId = adEmployee?.employeeID;
                    const name = adEmployee.name;

                    console.log(empId);

                    const newUser= await prisma.user.findUnique({
                      where:{
                        oracleId:oracleId
                      }
                    })

                    if(!newUser){
                      await prisma.user.create({
                        data:{
                          oracleId:empId,
                          fullName:name
                        }
                      })
                    }
                      
                  });
                }
              );
            }
          );
        });
      },
    }),
  ],
  pages: {
    signIn: "/auth/sign-in",
  },
  callbacks: {
    jwt: async ({ token, user }) => {
      if (user) {
        token.username = user.username;
        token.password = user.password;
      }
      return token;
    },
    session: async ({ session, token }) => {
      if (token) {
        session.id = token.id;
        session.username = token.username;
      }
      // console.log(token);
      return session;
    },
  },
  debug: process.env.NODE_ENV === "development",
  secret: process.env.NEXTAUTH_SECRET,
  jwt: {
    secret: process.env.NEXTAUTH_SECRET,
    encryption: true,
  },
});

`

promise 中不允许等待,我应该在哪里调用 prisma. 谢谢

为此你需要使用 API 端点(因为 prisma 在服务器端使用,不能在客户端使用,特别是当你从 env 传递 db url 时也没有在前端显示) ,例如您创建 /api/register 其中:

import { PrismaClient } from '@prisma/client';
import dotenv from 'dotenv' 
dotenv.config();
const prisma = new PrismaClient();

const Handler = async (
    req,
    res
) => {
    await prisma.$connect()
    const users = await prisma.user.findMany()
    //check if user u add is already in db
    //if not then
        try {
            savedUser = await prisma.user.create({ data: new_user });
            await prisma.$disconnect()
        } catch (error: any) {
            await prisma.$disconnect()
            // show db error
            return res.status(501).json({message: error.message})
        }
        res.status(200).json({ message: 'User added to db ' + savedUser.name });

}

这只是一个简单的说明,说明您需要做什么才能使其正常工作,您可以添加一些安全措施:

const { username, password } = req.body
if (req.method !== 'POST') {
    return res.status(405).json({ message: 'Method not allowed' });
    
}

if (!username || !password) {
    return res.status(400).json({ message: 'Username and password are required' });
}

然后你调用 api 端点:

    const response = await axios.post(
        LOGIN_URL,
        JSON.stringify({ username, password }),
        {
            headers: { 'Content-Type': 'application/json' },
            withCredentials: true
        }
    )

其中 LOGIN_URL 可能是 /api/register