使用NextAuth.js对接Strapi登录时出现CLIENT_FETCH_ERROR问题排查
NextAuth.js凭证认证CLIENT_FETCH_ERROR问题排查
问题场景
在Next.js(前端)+ Strapi(后端)的开发环境中配置NextAuth.js凭证认证,调用signIn函数登录用户时触发CLIENT_FETCH_ERROR。
相关配置与代码
1. .env配置
NEXT_PUBLIC_API_URL = http://127.0.0.1:1337/api NEXTAUTH_URL = http://localhost:3000/ NEXTAUTH_SECRET =
2. app/api/auth/[...nextauth].js
import CredentialsProvider from "next-auth/providers/credentials" import NextAuth from "next-auth/next"; const authOptions = { session:{ strategy:'jwt' }, pages: { signIn: '/auth/signin', }, providers: [ CredentialsProvider({ name: 'credentials', credentials: { email: { label: "email", type: "email", placeholder: "email" }, password: { label: "Password", type: "password" } }, async authorize(credentials, req) { const credentialDetails = { identifier: credentials.email, password: credentials.password, }; const res = await fetch(process.env.NEXT_PUBLIC_API_URL + "/auth/local", { method: 'POST', body: JSON.stringify(credentialDetails), headers: { "Content-Type": "application/json" } }) const user = await res.json() if (res.ok && user) { return user } return null } }) ], secret: process.env.NEXTAUTH_SECRET, callbacks: { jwt: async ({ token, user }) => { if (user) { token.email = user.user.email; token.username = user.user.username; token.id = user.user.id; token.accessToken = user.jwt; } return token; }, session: ({ session, token, user }) => { if (token) { session.user.email = token.email; session.user.username = token.username; session.user.id = token.id; session.user.accessToken = token.accessToken; } return session; }, }, } export default NextAuth(authOptions)
3. app/auth/signin/page.js
'use client' import {React, useState} from 'react' import {signIn} from "next-auth/react" function page() { const [data, setData] = useState({ email : "", password : "" }) const loginUser = (e) => { e.preventDefault(); signIn('credentials', { email: data.email, password: data.password, redirect: false, }) } return ( <> <h1>Login</h1> <form method="post" onSubmit={loginUser}> <label> Email <input name="email" type="text" onChange={ (e)=>{setData({...data,email:e.target.value})} } /> </label> <label> Password <input name="password" type="password" onChange={ (e)=>{setData({...data,password:e.target.value})} }/> </label> <button type="submit">Sign in</button> </form> </> ) } export default page
错误原因与修复方案
1. 未配置NEXTAUTH_SECRET
NextAuth.js强制要求设置NEXTAUTH_SECRET,空值会导致认证流程中的加密/解密操作失败,直接触发CLIENT_FETCH_ERROR。
修复:
用openssl rand -hex 32命令生成随机密钥,填入.env:
NEXTAUTH_SECRET = 你的随机密钥字符串
2. Fetch请求未处理异常
当前authorize函数中,若Strapi服务未启动、网络不通或接口地址错误,fetch会抛出异常,但代码未捕获,导致NextAuth内部处理失败。
修复:
给fetch添加try/catch捕获异常:
async authorize(credentials, req) { try { const credentialDetails = { identifier: credentials.email, password: credentials.password, }; const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/local`, { method: 'POST', body: JSON.stringify(credentialDetails), headers: { "Content-Type": "application/json" } }) const user = await res.json() if (res.ok && user) { return user } } catch (error) { console.error("Strapi接口请求失败:", error); } return null }
3. 环境变量URL格式问题
NEXTAUTH_URL末尾的斜杠可能导致NextAuth内部路由解析异常,建议去掉:
NEXTAUTH_URL = http://localhost:3000
4. 登录请求未处理错误反馈
当前signIn调用后未处理返回结果,无法直观排查具体错误。可以添加错误捕获:
const loginUser = async (e) => { e.preventDefault(); const result = await signIn('credentials', { email: data.email, password: data.password, redirect: false, }) if (result.error) { console.error("登录错误:", result.error); // 可在此处给用户展示错误提示 } }
额外检查点
- 确认Strapi服务正常运行在
http://127.0.0.1:1337 - 用Postman等工具测试Strapi的
/api/auth/local接口是否可用 - 检查防火墙/安全软件是否拦截了Next.js与Strapi之间的请求
内容的提问来源于stack exchange,提问作者VincentAb
相关产品推荐
相关产品推荐

