使用新的1.0 SDK为firebase生成带云功能的自定义身份验证令牌

时间:2018-04-04 16:52:26

标签: firebase google-cloud-functions

<?php // Navigation Menus register_nav_menus (array( 'primary' => --('Primaty Menu') )); ?> 开始,firebase-admin@5.11.0 firebase-functions@1.0.0在应用初始化时不再接受应用配置。

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

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

3 个答案:

答案 0 :(得分:2)

基于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'};
                });
});

答案 1 :(得分:1)

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,并将时间写入数据库位置,从而触发云功能。

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

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

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

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

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

答案 2 :(得分:0)

由于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);
            });
        });
});