【问题标题】:Firebase ID token has incorrect "aud" (audience) claim when calling from Endpoint connected to Google Functions从连接到 Google Functions 的端点调用时,Firebase ID 令牌的“aud”(受众)声明不正确
【发布时间】:2020-05-06 13:53:03
【问题描述】:

我使用 Google Endpoints 作为在 Google Run 容器服务中运行的 API 网关。 API 路径指向 Google 函数(节点 js)。对 API 网关的调用来自 Web 应用程序(即浏览器)。

其中一条路径是:/login,它使用 firebase.auth().signInWithEmailAndPassword 方法在 firebase 中对用户进行身份验证。我得到用户的令牌 ID 并将其在响应标头(身份验证承载)中发送回浏览器。这按预期工作。

当向端点发出其他请求(例如/check)时,令牌(在标头中)被包括在内。我想在处理任何请求之前使用 Firebase Admin 方法检查令牌的有效性。 Google Function 中为其中一个路由执行此操作的代码如下:

...

const decodeIdToken = async (req, res, next) => {
  // Read the ID Token from the Authorization header.
  const idToken = req.headers.authorization.split('Bearer ')[1];
  try {
    const decodedIdToken = await admin.auth().verifyIdToken(idToken);
    req.decodedToken = decodedIdToken;
    next();
    return;
  } catch (error) {
    return res.status(403).json({
      status: 'failure',
      data: null,
      error: error.message
    });
  }
};

// use decodeIdToken as middleware
app.post('/check', decodeIdToken, (req, res, next) => {
  return res.json({
    status: 'success',
    data: req.decodedToken,
    error: null
  });
});

当我通过直接调用 Google 函数触发器来调用(通过 Postman)路由时,两条路由都可以工作。但是,当我调用指向 Google 函数的 Google Endpoints 时,我在使用 Firebase Admin 对象时收到以下错误:

Firebase ID 令牌的“aud”(受众)声明不正确。应为 \"PROJECT-ID\",但得到的是 \"https://us-central1-PROJECT-ID.cloudfunctions.net/FUNCTION-NAME\"。确保 ID 令牌与用于验证此 SDK 的服务帐户来自同一个 Firebase 项目。有关如何检索 ID 令牌的详细信息,请参阅 https://firebase.google.com/docs/auth/admin/verify-id-tokens

在 NodeJs 中设置 Firebase Admin 对象时,我尝试了以下操作:

const admin = require('firebase-admin');
admin.initializeApp();

还有

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://PROJECT-ID.firebaseio.com"
});

【问题讨论】:

    标签: node.js firebase-authentication google-cloud-functions firebase-admin google-cloud-endpoints-v2


    【解决方案1】:

    下面的 worked 不起作用(见下面的评论):

    openapi-functions.yaml 中添加文档推荐的安全定义

    securityDefinitions:
        firebase:
          authorizationUrl: ""
          flow: "implicit"
          type: "oauth2"
          # Replace YOUR-PROJECT-ID with your project ID
          x-google-issuer: "https://securetoken.google.com/YOUR-PROJECT-ID"
          x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
          x-google-audiences: "YOUR-PROJECT-ID"
    

    然后,针对路径(在我的情况下为/check),添加安全部分,如下所示:

       /check:
          post:
            ...
            x-google-backend:
               ....
               ....
            security:
               - firebase: []
            ....
    

    参考:https://cloud.google.com/endpoints/docs/openapi/authenticating-users-firebase

    【讨论】:

    • 以上行不通。我误以为会。它显示的错误是“aud”是谷歌函数而不是项目ID。 google 函数未被调用但被 Google API 网关拒绝
    • 没有。 @体面梯度。从那以后,我离开了这个配置。所以我不知道
    【解决方案2】:

    使用X-Apigateway-Api-Userinfo 标头

    标头的值是 JWT 的 base64 编码负载。无需重新验证,因为 API Gateway 已经为您验证了令牌,并且内容可供您使用。

    Node.js 开发者示例:

    Buffer.from(req.header("x-apigateway-api-userinfo"), "base64").toString();
    

    如果出于某种原因您确实需要访问原始 JWT,则可以在 X-Forwared-Authorization 标头中找到它。


    不必要的额外积分:

    为了解释该错误,您收到错误 Audience 声明的原因是因为您尝试验证的 JWT 是由 API Gateway 生成的不同 JWT。原始授权标头已替换为此 JWT。为什么?它告诉 Cloud Functions “嘿,Cloud Function,是我 API 网关在给你打电话,这是一个签名的 JWT 来证明这一点”。因此 API Gateway 的受众最终是 Cloud Function 资源 url,而 Firebase 的受众是 Firebase 所在的项目。

    如果您问我,这只是另一个由于 Google 的实施而造成的奇怪不便的例子;他们绝对可以保持 Auth 标头不变,并让 API Gateway 使用不同的标头,但乞丐不能成为选择者。 ?‍♂️


    Reference API Gateway Documentation:

    在您的 API 中接收经过身份验证的结果

    API 网关通常会转发它收到的所有标头。但是,它在后端地址时会覆盖原始的 Authorization 标头 由 API 配置中的 x-google-backend 指定。

    API Gateway 会将 X-Apigateway-Api-Userinfo 中的认证结果发送到后端 API。建议使用 此标头而不是原始的 Authorization 标头。这个标题 采用 base64url 编码并包含 JWT 有效负载。

    【讨论】:

      猜你喜欢
      • 2020-06-20
      • 2020-06-29
      • 1970-01-01
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 2017-07-27
      • 2020-11-05
      • 2016-12-23
      相关资源
      最近更新 更多