NextAuth无法重定向到相对回调URL,需实现登录返回原受保护页面
解决NextAuth多语言站点登录后重定向回受保护页面的问题
核心问题分析
你当前的问题出在两个关键点:
- 未将用户当前访问的受保护页面完整路径作为
callbackUrl传递给signIn方法 redirect回调函数的URL拼接逻辑错误,导致带locale的路径重复无效
解决方案步骤
1. 传递正确的callbackUrl给signIn
在触发登录的按钮处,获取用户当前所在的完整路径(包含locale标识),将其作为callbackUrl传入signIn:
import { useRouter } from 'next/router'; // 组件内部逻辑 const router = useRouter(); const { asPath } = router; // 登录按钮代码 <Button fullWidth size="large" color="inherit" variant="outlined" onClick={() => signIn("google", { callbackUrl: asPath })} > 用Google登录 </Button>
这里asPath会自动包含当前页面的完整路径(比如/en-US/protected-dashboard或/id-ID/private-profile),确保登录后直接回到用户原本访问的页面。
2. 修复redirect回调函数
原逻辑会导致URL重复拼接(比如把/en-US/page处理成baseUrl/en-US//en-US/page),修改后的逻辑会正确校验并返回合法路径:
export default NextAuth({ adapter: MongoDBAdapter(clientPromise), secret: process.env.NEXTAUTH_SECRET, providers: [ GoogleProvider({ clientId: process.env.GOOGLE_ID, clientSecret: process.env.GOOGLE_SECRET, }), ], callbacks: { async redirect({ url, baseUrl }) { // 处理相对路径(带locale的情况) if (url.startsWith('/')) { const absoluteUrl = new URL(url, baseUrl); if (absoluteUrl.origin === baseUrl) { return absoluteUrl.toString(); } } // 校验绝对URL是否属于当前域名 try { const urlObj = new URL(url); if (urlObj.origin === baseUrl) { return url; } } catch (e) { // 无效URL返回首页 return baseUrl; } // 非法路径统一返回首页 return baseUrl; } } })
3. 额外补充:受保护页面的跳转逻辑
如果你的受保护页面在用户未登录时需要跳转到登录页,记得把当前页面路径作为参数传递给登录页,比如:
// 受保护页面的登录校验逻辑 if (!session) { router.push(`/${locale}/login?callbackUrl=${encodeURIComponent(asPath)}`); }
然后在登录页从URL参数中获取callbackUrl,作为signIn的 fallback 值:
// 登录页组件内 const { query } = useRouter(); const callbackUrl = query.callbackUrl || `/${locale}/app`;
内容的提问来源于stack exchange,提问作者Febry Aryo
相关产品推荐
相关产品推荐

