部署Next.js至Firebase时.env配置引发Google认证超时故障求助
Next.js部署Firebase后NextAuth登录无响应,出现CLIENT_FETCH_ERROR
问题现象
- 本地两种场景运行正常:
.env中NEXTAUTH_URL设为http://localhost:3000,执行npm run dev无异常;.env中NEXTAUTH_URL设为http://localhost:5000,执行firebase serve无异常。
- 部署到Firebase后,将
NEXTAUTH_URL改为线上地址https://my-web-app.web.app,点击登录按钮无反应,数分钟后浏览器控制台出现错误:
[next-auth][error][CLIENT_FETCH_ERROR] https://next-auth.js.org/errors#client_fetch_error Unexpected token 'T', "Timed out "... is not valid JSON {error: {…}, url: '/api/auth/session', message: `Unexpected token 'T', "Timed out "... is not valid JSON`} client : true error : {message: `Unexpected token 'T', "Timed out "... is not valid JSON`, stack: `SyntaxError: Unexpected token 'T', "Timed out "... is not valid JSON`, name: 'SyntaxError'} message : "Unexpected token 'T', \"Timed out \"... is not valid JSON" url : "/api/auth/session" [[Prototype]] : Object
已确认事项
- Firebase与Next.js版本兼容
- Google Cloud Console配置正确
相关代码
app/api/auth/[...nextauth].js
import NextAuth from "next-auth/next"; import GoogleProvider from "next-auth/providers/google"; const handler = NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID , clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), ], secret: process.env.NEXTAUTH_SECRET, }); export { handler as GET, handler as POST };
登录按钮组件
import { useSession, signIn, signOut } from "next-auth/react" export default function SignInButton() { const { data: session } = useSession() if (session) { return ( <> Signed in as {session.user.email} <br /> <button onClick={() => signOut()}>Sign out</button> </> ) } return ( <> Not signed in <br /> <button onClick={() => signIn("google")}>Sign in</button> </> ) }
根布局layout.js
export const metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default function RootLayout({ children }) { return ( <html lang="en"> <body className={inter.className}> <Provider > <SignInButton/> {children} </Provider></body> </html> ) }
Providers.js组件
"use client" import { SessionProvider } from "next-auth/react" import {Session} from "next-auth" const session = Session; export default function Provider({ children }) { return ( <SessionProvider session={session} children={children}> {children} </SessionProvider> ) }
解决方案
1. 修复SessionProvider的参数错误
你的Providers.js错误地将Session类型赋值给session变量,导致SessionProvider传入无效对象,引发会话请求超时。修改如下:
修改Providers.js
"use client" import { SessionProvider } from "next-auth/react" export default function Provider({ children, session }) { return ( <SessionProvider session={session}> {children} </SessionProvider> ) }
修改根布局layout.js
需要从服务端获取会话并传递给Provider,同时确保引入必要依赖:
import { getServerSession } from "next-auth/next" import { authOptions } from "./api/auth/[...nextauth]" import Provider from "./Providers" import SignInButton from "./SignInButton" import { Inter } from "next/font/google" const inter = Inter({ subsets: ['latin'] }) export const metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default async function RootLayout({ children }) { const session = await getServerSession(authOptions) return ( <html lang="en"> <body className={inter.className}> <Provider session={session}> <SignInButton/> {children} </Provider> </body> </html> ) }
修改[...nextauth].js
导出authOptions供根布局调用:
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, }), ], secret: process.env.NEXTAUTH_SECRET, }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
2. 确认Firebase线上环境变量
部署后需确保Firebase项目已配置以下环境变量(通过Firebase控制台或firebase functions:config:set命令设置):
NEXTAUTH_URLGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETNEXTAUTH_SECRET
本地.env文件的变量不会自动同步到线上。
3. 检查Firebase Hosting重写规则
确保firebase.json中的重写规则正确指向Next.js API路由:
{ "hosting": { "source": ".", "frameworksBackend": { "region": "us-central1" }, "rewrites": [ { "source": "/api/**", "function": "nextjs" }, { "source": "**", "destination": "/index.html" } ] } }
内容的提问来源于stack exchange,提问作者Njdc Wide
相关产品推荐
相关产品推荐

