如何实现Next.js 14 Web应用与Chrome扩展的认证状态同步?
实现方案
1. 搭建Next.js会话校验API端点
在你的Next.js项目中创建一个专门用于校验认证状态的API路由,通过NextAuth的getServerSession判断用户会话有效性:
// app/api/auth/check-session/route.ts import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { NextResponse } from "next/server"; export async function GET() { const session = await getServerSession(authOptions); if (!session) { return NextResponse.json({ authenticated: false }, { status: 401 }); } return NextResponse.json({ authenticated: true, user: { name: session.user?.name, email: session.user?.email // 按需返回必要的用户信息 } }); }
2. 调整NextAuth的Cookie配置
为了让Chrome扩展能携带主站的会话Cookie,需要修改NextAuth的Cookie参数,适配扩展的上下文:
// app/api/auth/[...nextauth]/route.ts export const authOptions: NextAuthOptions = { // 其他原有配置(如providers、secret等) cookies: { sessionToken: { name: `__Secure-next-auth.session-token`, options: { httpOnly: true, sameSite: process.env.NODE_ENV === "production" ? "None" : "Lax", path: "/", secure: process.env.NODE_ENV === "production", domain: process.env.NEXT_PUBLIC_APP_DOMAIN, // 填写你的主站根域名,如example.com }, }, // 其余Cookie(如callbackUrl、csrfToken)同理调整sameSite和domain }, };
说明:生产环境下将
sameSite设为None并开启secure,确保跨上下文的Cookie能被携带;开发环境用Lax即可。
3. 配置Chrome扩展权限
在扩展的manifest.json中添加主站API的访问权限,确保请求能携带Cookie:
{ "manifest_version": 3, "name": "你的扩展名称", "version": "1.0", "permissions": ["storage"], "host_permissions": ["https://你的主站域名/*"], // 替换为实际主站域名 "action": { "default_popup": "popup.html" }, "chrome_url_overrides": { "newtab": "newtab.html" // 如果你用扩展替换新标签页 }, "content_security_policy": { "extension_pages": "script-src 'self'; object-src 'none'" } }
4. 扩展端实现认证状态校验
在扩展的弹出页或新标签页JS中,调用校验API判断用户状态,切换对应内容:
// popup.js 或 newtab.js async function checkAuthStatus() { try { const response = await fetch("https://你的主站域名/api/auth/check-session", { credentials: "include", // 关键:携带Cookie发送请求 method: "GET" }); const data = await response.json(); if (data.authenticated) { // 展示已登录内容 document.getElementById("logged-in").style.display = "block"; document.getElementById("logged-out").style.display = "none"; document.getElementById("user-name").textContent = data.user.name; } else { // 展示未登录内容(如跳转主站登录的按钮) document.getElementById("logged-in").style.display = "none"; document.getElementById("logged-out").style.display = "block"; } } catch (err) { console.error("校验认证状态失败:", err); document.getElementById("logged-out").style.display = "block"; } } // 页面加载时自动校验 document.addEventListener("DOMContentLoaded", checkAuthStatus);
5. 扩展调用受保护API路由
已登录用户调用主站受保护API时,同样需要携带Cookie:
async function callProtectedAPI() { try { const response = await fetch("https://你的主站域名/api/protected-endpoint", { credentials: "include", method: "GET" }); if (!response.ok) throw new Error("API请求失败"); const data = await response.json(); // 处理返回的业务数据 console.log("受保护API响应:", data); } catch (err) { console.error("调用受保护API失败:", err); // 未授权时跳转主站登录页 window.open("https://你的主站域名/auth/signin", "_blank"); } }
关键注意事项
- 确保主站与扩展使用同一根域名,否则跨域Cookie携带会受浏览器安全策略限制。
- Manifest V3环境下,禁止使用内联脚本,所有JS代码需放在单独文件中。
- 开发环境测试时,若遇到SameSite Cookie拦截,可在Chrome的
chrome://flags/#same-site-by-default-cookies中关闭该选项。
内容的提问来源于stack exchange,提问作者Ernie
相关产品推荐
相关产品推荐

