Next.js集成next-auth中间件登录成功后仍重定向至登录页问题
问题描述
我使用next-auth.js接入Google作为登录服务提供商,后端采用Django框架。为实现Next.js的页面访问权限保护,我参考next-auth官方文档的中间件章节尝试集成next-auth.js与Next.js中间件。
当前遇到的问题:用户未登录状态下,中间件可以正常跳转到登录页;但用户完成登录操作后,依然会被重定向回登录页。
现有配置
middleware.js
export { default } from "next-auth/middleware" export const config = { matcher: ["/jobs/:path*", "/accounts/:path*", "/profile/:path*", "/uploads/:path*"] }
/pages/api/auth/[...nextauth.js]
import axios from "axios"; import NextAuth from "next-auth" import Google from "next-auth/providers/google"; import { isJwtExpired } from "../../../constants/Utils"; async function refreshAccessToken(token) { try { const response = await axios.post( process.env.NEXT_PUBLIC_BACKEND_BASE + "/api/auth/token/refresh/", { refresh: token.refreshToken }); const { access, refresh } = response.data; return { ...token, accessToken: access, refreshToken: refresh, } } catch (error) { console.log(error) return { ...token, error: "RefreshTokenError" } } } export default NextAuth({ providers: [ Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, authorization: { params: { access_type: "offline", response_type: "code", scope:'openid profile email' } } }), ], callbacks: { async jwt({ token, user, account}) { // Initial sign in if (account && user) { if (account.provider === "google") { const { access_token: accessToken } = account; try { // 向DRF后端发起请求交换自有token const response = await axios.get( process.env.NEXT_PUBLIC_BACKEND_BASE + "/api/auth/register-by-token/google-oauth2/", { params: { access_token: accessToken } } ); const { access, refresh } = response.data; token = { ...token, accessToken: access, refreshToken: refresh, }; return token } catch (error) { console.log(error) return { ...token, error: "NewUserTokenError" } } } return { ...token, error: "InvalidProviderError" } } if (isJwtExpired(token.accessToken)) { return refreshAccessToken(token) } else { return token } }, async session({ session, token }) { session.accessToken = token.accessToken session.refreshToken = token.refreshToken session.error = token.error return session } } })
问题原因
登录后仍被重定向到登录页,核心是next-auth中间件没有通过登录态校验,配置存在3个明确问题:
- 缺少必填的
NEXTAUTH_SECRET配置
next-auth对session cookie做签名加解密必须依赖secret值,未配置的场景下,虽然登录流程能走完、cookie能写入浏览器,但中间件侧无法解密校验cookie内容,会直接把用户判定为未登录状态,触发重定向。 - JWT回调逻辑存在边界bug
现有过期判断逻辑没有判断token.accessToken是否存在:首次登录流程走完后,jwt回调第一次触发后续校验时,存在时序问题导致accessToken还没完成赋值就进入过期判断,直接触发刷新token逻辑。如果此时refreshToken也不存在,刷新接口请求失败就会给token打上错误标记,中间件识别到错误标记就会判定登录失效。 - 自定义登录页路径未声明
如果用了自定义登录页但没有在next-auth配置里声明对应路径,中间件默认会把未登录请求重定向到内置的/api/auth/signin路径,若该路径没有部署登录页,就会出现重定向循环。
修复步骤
- 补全环境变量
在项目环境变量文件中新增NEXTAUTH_SECRET,值为随机字符串即可,本地可以执行openssl rand -hex 32生成,生产环境也要同步配置该值。 - 修正JWT回调的判断逻辑
把原有JWT回调里的过期判断部分替换为以下代码,补全存在性判断:
// 已有有效token直接返回 if (token.accessToken && !isJwtExpired(token.accessToken)) { return token } // 尝试刷新token,刷新失败时清空无效凭证避免死循环 try { return await refreshAccessToken(token) } catch (err) { return { ...token, accessToken: null, refreshToken: null, error: null } }
- 自定义登录页的话补全pages配置
如果没有用next-auth内置的登录页,在NextAuth初始化配置中添加pages字段:
pages: { signIn: '/your-real-login-path', // 替换成实际的登录页路由 }
- 清缓存验证
清除浏览器下当前域名的所有cookie,重启Next.js服务后重新走登录流程即可。
内容的提问来源于stack exchange,提问作者Viraj
相关产品推荐
相关产品推荐

