使用自定义令牌以管理员身份向 FB DB 发出 REST 请求

Using Custom Tokens to make REST requests to FB DB as an admin

我正在迁移到新数据库和 3.0 客户端库。我正在更新生成自定义身份验证令牌(在我们的服务器上)的部分,以执行 PATCH 更新 Firebase 数据库中的资源。

这些 PATCH 请求过去是由我们的服务器向 Firebase 发出的,使用 admin 声明基于此:https://www.firebase.com/docs/rest/guide/user-auth.htm

对于新数据库,我正在生成 JWT 令牌(使用 ruby-jwt),如下所示:

payload = {
  aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
  claims: custom_claims.merge({ admin: true }),
  exp: now_seconds + (60 * 60), # Maximum expiration time is one hour
  iat: now_seconds,
  iss: service_account_email,
  sub: service_account_email,
  uid: uid
}

JWT.encode(payload, private_key, "RS256")

使用此令牌向 Firebase DB 发出的 PATCH 请求失败:Missing claim 'kid' in auth header.

在新的 Firebase 中,您需要直接使用服务帐户来创建管理访问凭据。这是一个 Node.js 片段,展示了如何对数据库进行 REST 调用:

// key.json is a service account key downloaded from the Firebase Console
var key = require('./key.json');

var google = require('googleapis');
var request = require('request');

var DATABASE_URL = 'https://<databaseName>.firebaseio.com';

var jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, [
  'https://www.googleapis.com/auth/userinfo.email',
  'https://www.googleapis.com/auth/firebase.database'
]);

jwtClient.authorize(function(err, tokens) {
  request({
    url: DATABASE_URL + '/.json',
    method: 'GET',
    headers: {
      'Authorization': 'Bearer ' + tokens.access_token
    }
  }, function(err, resp) {
    console.log(resp.body);
  });
});

要在 Ruby 中执行相同操作,您可以查看 googleauth gem 以使用服务帐户凭据获取访问令牌。

以下是 Michael Bleigh 使用 ruby googleauth 模块的等效答案:

require 'googleauth'

scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/firebase.database']
auth = ::Google::Auth.get_application_default(scopes)
auth_client = auth.dup
auth_client.sub = "service-account-email-here@yourapp.iam.gserviceaccount.com"
token = auth_client.fetch_access_token!

您还需要将 GOOGLE_APPLICATION_CREDENTIALS 环境变量设置为您的服务帐户 JSON 文件的路径。 auth_client.sub 的值来自此 JSON 文件中的 client_email

当然,如上所述,这只在你控制的服务器应用程序中有效。

此外,向 firebase REST API 发出请求仍然是 reader 的练习。

参考文献