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

Firebase ID Token受众不匹配问题及登录系统开发求助

问题解决与后续开发指导

错误原因分析

你当前的核心问题是:用原生Google OAuth2流程获取的ID Token,无法被Firebase Admin SDK的verifyIdToken方法验证。

Google OAuth生成的ID Token,其aud(受众)字段是你的Google OAuth客户端ID(即错误日志里的1090170234957-5ntr48jf178o9befpp5n0603hoh7m2rh.apps.googleusercontent.com);而Firebase Admin的verifyIdToken仅能验证Firebase官方生成的ID Token,这类Token的aud字段是你的Firebase项目ID(错误日志里的school-progress-g),因此出现不匹配报错。


两种解决方案

方案一:直接验证Google ID Token(无需Firebase Auth整合)

如果你不需要依赖Firebase的其他功能,可以替换Firebase的验证逻辑,改用Google官方工具验证ID Token:

  1. 替换中间件代码:
const { OAuth2Client } = require('google-auth-library');
// 传入你的Google OAuth客户端ID
const googleAuthClient = new OAuth2Client("1090170234957-5ntr48jf178o9befpp5n0603hoh7m2rh.apps.googleusercontent.com");

const authMiddleware = async (req, res, next) => {
  const idToken = req.cookies.idToken || "";
  
  if (!idToken) {
    return next();
  }

  try {
    // 验证Google ID Token
    const ticket = await googleAuthClient.verifyIdToken({
      idToken,
      audience: "1090170234957-5ntr48jf178o9befpp5n0603hoh7m2rh.apps.googleusercontent.com",
    });
    req.user = ticket.getPayload();
    next();
  } catch (error) {
    console.log(error);
    // 验证失败时清除无效Cookie并跳转登录
    res.clearCookie("idToken");
    res.redirect("/login");
  }
};
app.use(authMiddleware);
  1. 移除代码中Firebase Admin相关的初始化逻辑(如果不需要其他Firebase服务)。

方案二:整合Firebase Auth(推荐,可复用Firebase生态)

如果需要使用Firebase的数据库、存储等功能,建议将Google登录流程接入Firebase Auth,获取Firebase官方ID Token:

步骤1:配置Firebase控制台

在Firebase控制台的「Authentication」-「登录方法」中启用Google登录,填入你当前使用的Google OAuth客户端ID和密钥,确保回调URL与代码中一致。

步骤2:修改后端代码

替换/callback路由和验证中间件,将Google授权码转换为Firebase会话凭证:

// 替换原有的callback路由
app.get("/callback", async (req, res) => {
  try {
    const { tokens } = await oauth2Client.getToken(req.query.code);
    // 用Google ID Token创建Firebase凭证
    const googleCredential = admin.auth.GoogleAuthProvider.credential(tokens.id_token, tokens.access_token);
    
    // 获取或创建Firebase用户
    const userRecord = await admin.auth().getUserByEmail(tokens.id_token_payload.email).catch(async () => {
      // 若用户不存在,自动创建
      return admin.auth().createUser({
        email: tokens.id_token_payload.email,
        emailVerified: true,
        displayName: tokens.id_token_payload.name,
      });
    });

    // 生成Firebase会话Cookie(比ID Token更适合后端会话管理)
    const sessionCookie = await admin.auth().createSessionCookie(tokens.id_token, {
      expiresIn: 60 * 60 * 24 * 5 * 1000, // 5天有效期
    });

    // 设置HttpOnly、Secure的Cookie(生产环境必须开启Secure)
    const cookieOptions = {
      maxAge: 60 * 60 * 24 * 5 * 1000,
      httpOnly: true,
      secure: process.env.NODE_ENV === "production",
    };
    res.cookie("session", sessionCookie, cookieOptions);
    res.redirect("/app");
  } catch (error) {
    console.error(error);
    res.redirect("/login");
  }
});

// 替换原有的验证中间件
const firebaseAuthMiddleware = async (req, res, next) => {
  const sessionCookie = req.cookies.session || "";
  
  if (!sessionCookie) {
    return res.redirect("/login");
  }

  try {
    // 验证Firebase会话Cookie
    const decodedClaims = await admin.auth().verifySessionCookie(sessionCookie, true);
    req.user = decodedClaims;
    next();
  } catch (error) {
    console.log(error);
    res.clearCookie("session");
    res.redirect("/login");
  }
};
app.use(firebaseAuthMiddleware);

后续开发指导

  1. 会话安全:

    • 生产环境必须为Cookie添加secure: true(仅通过HTTPS传输),防止明文泄露。
    • 启用httpOnly: true避免XSS攻击窃取Cookie。
  2. 权限控制:

    • 在中间件中验证用户身份后,可通过req.user.email或req.user.uid判断用户权限(比如仅允许指定学校邮箱的用户访问管理功能)。
    • 可在Firebase控制台为用户设置自定义Claims(如admin: true),实现更细粒度的权限控制。
  3. 错误处理优化:

    • 验证失败时直接跳转登录页,避免未授权用户进入受保护路由。
    • 为不同错误类型(如Token过期、无效)添加针对性提示。
  4. 用户数据管理:

    • 将用户的设置、角色等信息存储到Firebase Realtime Database或Firestore,便于后续读取和更新。
    • 注销时调用admin.auth().revokeRefreshTokens(req.user.uid)彻底撤销用户的所有会话。
  5. 前端配合:

    • 若前端需要获取用户信息,可从后端接口返回req.user的关键字段(如邮箱、用户名),避免直接暴露敏感数据。

内容的提问来源于stack exchange,提问作者Grantie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:27:06