【问题标题】:Generating a custom auth token with a cloud function for firebase using the new 1.0 SDK使用新的 1.0 SDK 为 firebase 生成具有云功能的自定义身份验证令牌
【发布时间】:2018-09-14 08:03:16
【问题描述】:

firebase-admin@5.11.0firebase-functions@1.0.0 开始,firebase-admin 在应用初始化时不再接受应用配置。

我有一个 firestore 函数,可以使用 firebase-admin 的 createCustomToken 生成自定义令牌。调用该函数将生成一个凭据,我将在credential 属性中将其传递给initializeApp。我现在该怎么做?

我是否需要以某种方式编辑process.env.FIREBASE_CONFIG 并在调用initializeApp 之前将序列化凭据放在那里?

【问题讨论】:

    标签: firebase google-cloud-functions


    【解决方案1】:

    基于 Github 中的这个问题,它仍然有效。

    https://github.com/firebase/firebase-admin-node/issues/224

    以下示例对我有用:

    const functions = require('firebase-functions');
    const admin = require('firebase-admin');
    const serviceAccount = require('./serviceAccountKey.json');
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: 'https://yourapplication.firebaseio.com/'
      });
    
    exports.createToken = functions.https.onCall((data, context) => {
        const uid = context.auth.uid;
        return admin.auth()
                    .createCustomToken(uid)
                    .then(customToken => {
                        console.log(`The customToken is: ${customToken}`);
                        return {status: 'success', customToken: customToken};
                    })
                    .catch(error => {
                        console.error(`Something happened buddy: ${error}`)
                        return {status: 'error'};
                    });
    });
    

    【讨论】:

    • 欢迎来到 SO。尽管提供指向源的链接是一个好主意(正如您所做的那样)。将相关文本/代码复制到您的答案中也是一个好主意。这样,如果链接更改内容或停止工作,您的答案仍然有价值。
    【解决方案2】:

    Michael Chen 的云功能似乎是从某个地方(外部服务器?)的 HTTP 请求触发的。我的员工写了一个在用户登录时触发的云函数:

    // this watches for any updates to the user document in the User's collection (not subcollections)
    exports.userLogin = functions.firestore.document('Users/{userID}').onUpdate((change, context) => {
    
      // save the userID ubtained from the wildcard match, which gets put into context.params
      let uid = context.params.userID;
      // initialize basic values for custom claims
      let trusted = false;
      let teaches = [];
    
      // check the Trusted_Users doc
      admin.firestore().collection('Users').doc('Trusted_Users').get()
      .then(function(doc) {
        if (doc.data().UIDs.includes(uid)) {
          // if the userID is in the UIDs array of the document, set trusted to true.
          trusted = true;
        }
    
        // Get docs for each language in our dictionary
        admin.firestore().collection('Dictionaries').get()
        .then(function(docs) {
          // for each of those language docs
          docs.forEach(function(doc) {
            // check if the userID is included in the trustedUIDs array in the doc
            if (doc.data().trustedUIDs.includes(uid)) {
              // if it is, we push the 2-letter language abbreviation onto the array of what languages this user teaches
              teaches.push(doc.data().shortLanguage);
            }
          });
    
          // finally, set custom claims as we've parsed
          admin.auth().setCustomUserClaims(uid, {'trusted': trusted, 'teaches': teaches}).then(() => {
            console.log("custom claims set.");
          });
        });
      });
    });
    

    首先,我们在用户对象上放入lastLogin 属性,当用户登录时运行 Date.now 并将时间写入数据库位置,触发云功能。

    接下来,我们从云函数响应context.params.userID获取userID

    然后初始化两个变量。我们假设用户不被信任,除非另有证明。另一个变量是用户教授的主题数组。在基于角色的数据安全系统中,这些是允许用户访问的集合。

    接下来,我们访问列出受信任用户的用户 ID 的文档。然后我们检查最近登录的用户 ID 是否在这个数组中。如果是这样,我们将trusted 设置为true

    接下来,我们进入数据库并遍历集合Dictionaries,其文档包含受信任的用户 ID 数组(即,允许读取和写入这些文档的用户)。如果用户在这些数组中的一个或多个中,他或她会将该文档添加到他或她的用户数据的teaches 属性中,从而使用户可以访问该文档。

    最后,我们准备运行setCustomUserClaims 来自定义令牌声明。

    【讨论】:

      【解决方案3】:

      感谢Thomas's answer,这是可调用云函数的变体

      一旦设置了自定义声明,您就可以访问/从……例如 firebase 存储规则中的字段。

      例如:
      allow write: if request.auth.token.isAppAdmin == true;

      使用可调用的云函数,只要在承诺链的某处返回 admin.auth().setCustomUserClaims(..) 函数,声明字段就会添加到 request.auth.token 对象中:

      const functions = require('firebase-functions');
      exports.setIsAdminClaim = functions.https.onCall((data, context) => {
      
          var uid = context.auth.uid;
          return admin.auth().setCustomUserClaims(
                  uid, {
                      isAppAdmin: true
                  }
              )
              .then(() => {
                  var msg = 'isAppAdmin custom claim set';
                  console.log(msg);
      
                  return new Promise(function (resolve, reject) {
      
                      var resolveObject = {
      
                          message : msg
                      };
      
                      resolve(resolveObject);
                  });
              });
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-19
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2017-07-03
        • 1970-01-01
        • 2017-08-14
        • 2017-12-19
        相关资源
        最近更新 更多