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

移动端API认证:不推荐用idToken,求accessToken服务端验证方案

基于Firebase生态的理想认证实现方案

1. 理清Token类型的对应关系

Auth0提到的「ID Token用于身份验证、Access Token用于API访问」原则,在Firebase体系中可这样对齐:

  • Firebase的ID Token本身兼具身份验证与API授权能力,官方默认推荐用它做移动端到Cloud Functions的认证;如果要严格区分身份凭证与API访问凭证,可通过自定义JWT实现专属的Access Token。

2. 移动端Token获取与API调用

  • 移动端通过Firebase Auth完成登录后,调用getIdToken()方法获取ID Token(默认1小时过期,需定期刷新),请求Cloud Functions时将Token放在Authorization头中,格式为Bearer <idToken>。
  • 若需专门的Access Token,可先调用专用Cloud Functions接口,传入refreshToken换取自定义生成的Access Token,再用该Token调用其他API。

3. Cloud Functions端的Token验证(官方推荐方案)

使用Firebase Admin SDK验证ID Token是最直接的方式,步骤如下:

  1. 安装依赖:
    npm install firebase-admin --save
    
  2. 编写验证中间件并在API中使用:
    const admin = require('firebase-admin');
    admin.initializeApp();
    
    async function verifyIdToken(req, res, next) {
      const idToken = req.headers.authorization?.split('Bearer ')[1];
      if (!idToken) return res.status(401).send('Unauthorized');
      
      try {
        const decodedToken = await admin.auth().verifyIdToken(idToken);
        req.user = decodedToken;
        next();
      } catch (err) {
        return res.status(403).send('Invalid token');
      }
    }
    
    // 示例API函数
    exports.userDataApi = functions.https.onRequest((req, res) => {
      verifyIdToken(req, res, () => {
        // 此处处理业务逻辑,req.user包含用户uid、邮箱等身份信息
        res.status(200).send({ uid: req.user.uid });
      });
    });
    

4. 自定义Access Token的实现方案(严格遵循ID Token不碰API的原则)

若要完全分离身份凭证与API访问凭证,可通过自定义JWT实现Access Token:

步骤1:移动端换取Access Token

编写Cloud Functions接口,接收refreshToken并生成自定义Access Token:

const jwt = require('jsonwebtoken');
const serviceAccount = require('./path/to/service-account-key.json');

exports.getAccessToken = functions.https.onRequest(async (req, res) => {
  const refreshToken = req.body.refreshToken;
  if (!refreshToken) return res.status(400).send('Refresh token required');
  
  try {
    const userRecord = await admin.auth().verifyRefreshToken(refreshToken);
    // 生成有效期15分钟的自定义JWT
    const accessToken = jwt.sign(
      {
        uid: userRecord.uid,
        scope: 'api:read api:write' // 自定义权限声明
      },
      serviceAccount.private_key,
      {
        algorithm: 'RS256',
        issuer: serviceAccount.client_email,
        expiresIn: '15m'
      }
    );
    res.status(200).send({ accessToken });
  } catch (err) {
    res.status(403).send('Invalid refresh token');
  }
});

步骤2:API端验证自定义Access Token

编写验证中间件验证JWT签名与有效性:

async function verifyAccessToken(req, res, next) {
  const accessToken = req.headers.authorization?.split('Bearer ')[1];
  if (!accessToken) return res.status(401).send('Unauthorized');
  
  try {
    const decoded = jwt.verify(
      accessToken,
      serviceAccount.public_key,
      {
        issuer: serviceAccount.client_email,
        algorithms: ['RS256']
      }
    );
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(403).send('Invalid access token');
  }
}

// 在API函数中使用该中间件
exports.protectedApi = functions.https.onRequest((req, res) => {
  verifyAccessToken(req, res, () => {
    // 处理权限校验与业务逻辑
    res.status(200).send('Access granted');
  });
});

5. 最佳实践总结

  • 在Firebase生态中,使用ID Token认证Cloud Functions是官方推荐的安全方案,无需额外自定义,已满足短过期、可验证、防篡改等要求。
  • 若坚持严格分离身份凭证与API访问凭证,自定义JWT Access Token是可行方案,但需自行管理签名密钥、过期时间与权限声明。
  • 所有Token传输必须通过HTTPS,避免明文泄露;移动端需定期刷新Token,确保凭证有效性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 06:23:14