Next.js App Router中NextAuth Firebase适配器用户与会话异常问题
启用NextAuth Firebase适配器后凭证登录失败,用户未写入Firestore
问题现象
- 启用Firestore适配器后,Credentials凭证登录始终处于未认证状态,Firestore数据库中无用户数据写入
- 移除适配器后,所有登录方式功能恢复正常
- Google、GitHub、Discord等第三方登录在启用适配器时可正常工作,仅凭证登录出现异常
NextAuth配置代码
export const authOptions : NextAuthOptions = { pages: { signIn: '/auth/login', }, providers: [ CredentialsProvider({ name: "Credentials", credentials: { }, async authorize(credentials) : Promise<any> { return await signInWithEmailAndPassword(auth, (credentials as any).email || '', (credentials as any).password || '') .then(userCredential => { if (userCredential.user) { return userCredential.user } return null }) .catch(error => console.log(error)) } }), GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET! }), GitHubProvider({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! }), DiscordProvider({ clientId: process.env.DISCORD_CLIENT_ID, clientSecret: process.env.DISCORD_CLIENT_SECRET }), ], /* adapter: FirestoreAdapter({ credential: cert({ projectId: process.env.FIREBASE_PROJECT_ID, clientEmail: process.env.FIREBASE_CLIENT_EMAIL, privateKey: process.env.FIREBASE_PRIVATE_KEY!.replace(/\\n/g, '\n') }) }) */ // adapter: FirestoreAdapter(db.app) } export default NextAuth(authOptions)
凭证注册代码
const signup = (formdata : FormData) => { setEmail((formdata.get("email") as string)) setPassword((formdata.get("password") as string)) createUserWithEmailAndPassword(auth, email, password).then(res => { console.log(res) }); router.push("/dashboard") }
第三方提供商注册代码
function Signup(provider : string) { signIn(provider) } // provider 取值为 google、github、discord
解决方案
1. 修正CredentialsProvider的返回格式
Firestore适配器要求authorize方法返回符合NextAuth规范的用户对象,直接返回Firebase Auth的用户实例会缺少必要字段。修改authorize方法:
async authorize(credentials): Promise<any> { try { const userCredential = await signInWithEmailAndPassword(auth, credentials.email || '', credentials.password || '') const user = userCredential.user // 转换为适配器兼容的用户结构 return { id: user.uid, name: user.displayName, email: user.email, emailVerified: user.emailVerified, image: user.photoURL } } catch (error) { console.error(error) return null } }
2. 正确初始化Firebase适配器
使用Firebase Admin SDK的初始化实例来配置适配器,避免直接传递凭证:
// 单独文件初始化Firebase Admin import { initializeApp, getApps, cert } from 'firebase-admin/app' import { getFirestore } from 'firebase-admin/firestore' const serviceAccount = { projectId: process.env.FIREBASE_PROJECT_ID, clientEmail: process.env.FIREBASE_CLIENT_EMAIL, privateKey: process.env.FIREBASE_PRIVATE_KEY!.replace(/\\n/g, '\n') } if (!getApps().length) { initializeApp({ credential: cert(serviceAccount) }) } const db = getFirestore() // 在NextAuth配置中使用 adapter: FirestoreAdapter(db)
3. 完善凭证注册流程
当前注册仅创建Firebase用户,未触发NextAuth登录流程,导致状态无法同步。修改注册函数:
const signup = async (formdata: FormData) => { const email = formdata.get("email") as string const password = formdata.get("password") as string try { await createUserWithEmailAndPassword(auth, email, password) // 创建用户后调用NextAuth完成登录 await signIn('credentials', { email, password, redirect: false }) router.push("/dashboard") } catch (error) { console.error(error) } }
4. 验证权限与环境变量
- 确认Firebase服务账号拥有Firestore的写入权限(在Firebase控制台IAM中配置)
- 检查所有Firebase相关环境变量是否正确配置,确保
privateKey的换行符替换逻辑生效
内容的提问来源于stack exchange,提问作者specter
相关产品推荐
相关产品推荐

