You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:22:53