You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用MongoDB Adapter后NextAuth的CredentialsProvider登录失败

NextAuth搭配MongoDB Adapter与CredentialsProvider登录失败问题解决

问题描述

使用NextAuth结合MongoDB Adapter和CredentialsProvider实现用户名密码认证时,启用MongoDB Adapter后登录功能失效,禁用Adapter则可正常登录,推测CredentialsProvider的authorize处理器存在数据库访问异常。

代码示例

auth.js

import mongoose from "mongoose";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { User } from "@/app/models/User";
import bcrypt from "bcrypt";
import GoogleProvider from "next-auth/providers/google";
import { MongoDBAdapter } from "@auth/mongodb-adapter";
import clientPromise from "@/libs/mongoConnect";

export const authOptions = {
    secret: process.env.SECRET,
    adapter: MongoDBAdapter(clientPromise),
    providers: [
        GoogleProvider({
            clientId: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        }),
        CredentialsProvider({
            name: "credentials",
            id: "credentials",
            credentials: {
                username: {
                    label: "Email",
                    type: "email",
                    placeholder: "test@example.com",
                },
                password: { label: "Password", type: "password" },
            },
            async authorize(credentials, req) {
                const email = credentials?.email;
                const password = credentials?.password;

                mongoose.connect(process.env.MONGO_URL);
                const user = await User.findOne({ email });
                const passwordOk = user && bcrypt.compareSync(password, user.password);

                if (passwordOk) {
                    return user;
                }

                return null;
            },
        }),
    ],
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

mongoConnect.js

import { MongoClient } from "mongodb";

if (!process.env.MONGO_URL) {
    throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
}

const uri = process.env.MONGO_URL;
const options = {};

let client;
let clientPromise;

if (process.env.NODE_ENV === "development") {
    if (!global._mongoClientPromise) {
        client = new MongoClient(uri, options);
        global._mongoClientPromise = client.connect();
    }
    clientPromise = global._mongoClientPromise;
} else {
    client = new MongoClient(uri, options);
    clientPromise = client.connect();
}

export default clientPromise;

错误信息

登录失败,收到意外服务器错误提示,CredentialsProvider的authorize处理器疑似数据库访问异常。

已尝试操作

  • 反复检查数据库连接,禁用MongoDB Adapter时连接正常;
  • 尝试过MongoDB Adapter的多种实现方式,确保数据库访问正常。

解决方案

问题根源在于同时使用mongoose和MongoClient两个独立的数据库连接客户端,导致连接冲突,且authorize函数内重复建立mongoose连接加剧了问题。以下是修复步骤:

1. 统一数据库连接方式

移除authorize函数内的mongoose.connect调用,直接使用已有的clientPromise进行数据库操作,避免连接冲突:

修改auth.js中的authorize函数:

async authorize(credentials, req) {
    const email = credentials?.email;
    const password = credentials?.password;

    // 使用已初始化的MongoClient连接
    const client = await clientPromise;
    const db = client.db();
    // 查询MongoDB Adapter默认使用的users集合
    const user = await db.collection('users').findOne({ email });

    if (!user) return null;

    // 验证密码
    const passwordOk = bcrypt.compareSync(password, user.password);
    if (passwordOk) {
        // 返回符合NextAuth要求的用户对象,需将ObjectId转为字符串
        return {
            id: user._id.toString(),
            email: user.email,
            name: user.name || ''
        };
    }

    return null;
}

2. 调整Session策略(可选)

若仍存在异常,可显式设置Session策略为jwt,避免Adapter的数据库Session与CredentialsProvider冲突:
在authOptions中添加:

session: {
    strategy: "jwt"
}

3. 确保用户数据格式正确

  • 确保MongoDB中users集合内的账号文档包含password字段(需是bcrypt加密后的字符串);
  • Google登录创建的用户默认无password字段,不影响Credentials登录,只需保证手动创建的账号有正确加密的密码。

4. 移除冗余的mongoose依赖(可选)

若不再使用mongoose模型,可直接移除mongoose相关导入和User模型,进一步避免连接冲突。

内容的提问来源于stack exchange,提问作者hossi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:39:56