使用NextAuth+Firebase自定义谷歌登录页报错:无法转换undefined/null为对象
解决NextAuth自定义谷歌登录页面报错:Cannot convert undefined or null to object
问题场景
使用NextAuth结合Firebase实现谷歌登录自定义页面时,触发错误:Cannot convert undefined or null to object,相关代码如下:
api/auth/[...nextauth]/route.js
import NextAuth from "next-auth/next" import GoogleProvider from "next-auth/providers/google" export const authOptions = { providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET }) ], pages: { signIn: '/auth' } } const handler = NextAuth(authOptions); export { handler as GET, handler as POST }
auth/page.js
import { getProviders, signIn } from "next-auth/react"; export default function SignIn({ providers }) { return ( <> {Object.values(providers).map((provider) => ( <div key={provider.id}> <button onClick={() => signIn(provider.id)}>Sign in with {provider.name}</button> </div> ))} </> ); } export async function getServerSideProps() { const providers = await getProviders(); return { props: { providers, }, }; }
错误原因
- App Router不支持
getServerSideProps:你在Next.js 13+的App Router页面中使用了仅适用于Pages Router的getServerSideProps,导致providers无法正确获取,最终返回null/undefined,触发Object.values(providers)的报错。 getProviders使用场景错误:next-auth/react中的getProviders是为Client Components设计的,直接在服务端方法中调用会导致获取失败。- 环境变量加载异常:如果
GOOGLE_CLIENT_ID或GOOGLE_CLIENT_SECRET未正确配置/加载,会导致Google Provider初始化失败,providers为空。
修复方案
方案一:服务端直接从authOptions获取Providers(推荐)
利用已定义的authOptions直接获取providers,无需额外异步请求:
import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { signIn } from "next-auth/react"; export default async function SignIn() { const providers = authOptions.providers; return ( <> {providers.map((provider) => ( <div key={provider.id}> <button onClick={() => signIn(provider.id)}>Sign in with {provider.name}</button> </div> ))} </> ); }
方案二:将页面改为Client Component
通过客户端异步请求获取providers,需添加"use client"指令:
"use client"; import { getProviders, signIn } from "next-auth/react"; import { useEffect, useState } from "react"; export default function SignIn() { const [providers, setProviders] = useState(null); useEffect(() => { const fetchProviders = async () => { const res = await getProviders(); setProviders(res); }; fetchProviders(); }, []); if (!providers) return <div>Loading...</div>; return ( <> {Object.values(providers).map((provider) => ( <div key={provider.id}> <button onClick={() => signIn(provider.id)}>Sign in with {provider.name}</button> </div> ))} </> ); }
额外检查项
- 确认
.env.local文件中GOOGLE_CLIENT_ID和GOOGLE_CLIENT_SECRET配置正确,无拼写错误 - 重启开发服务器,确保环境变量重新加载
- 验证NextAuth版本为v4.20.0+,该版本开始完善App Router支持
内容的提问来源于stack exchange,提问作者oday telbany
相关产品推荐
相关产品推荐

