如何使用经过身份验证的ID令牌和数据库规则保护Firebase Cloud Function HTTP端点? [英] How to protect firebase Cloud Function HTTP endpoint using authenticated id token and database rules?

本文介绍了如何使用经过身份验证的ID令牌和数据库规则保护Firebase Cloud Function HTTP端点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

admin.auth().verifyIdToken(tokenId)
      .then((decoded) => res.status(200).send(decoded))

我了解verifyIdToken()可以从Firebase身份验证客户端验证用户ID令牌.但是,我们需要通过确保数据库查询受令牌中标识的用户为数据库定义的安全规则限制来保护我们的云功能.假设默认情况下admin SDK具有无限访问权限,那么如何将其访问权限限制为仅通过身份验证的用户?

I understand verifyIdToken() can verify a user id token from Firebase Authentication clients. However we need to protect our Cloud Function by making sure database queries are limited by the security rules defined for the database for the user identified in the token. Given that the admin SDK has unlimited access by default, how to I limit its access to just that of the authenticated user?

推荐答案

看看下面的HTTPS函数.它执行以下任务:

Take a look at the following HTTPS function. It performs the following tasks:

  1. 使用Admin SDK验证Firebase身份验证ID令牌.令牌来自查询字符串(但您应该使用更好的解决方案传输令牌).
  2. 从解码的令牌中拉出用户的UID.
  3. 制作默认Firebase初始化配置对象的副本,然后添加一个名为 databaseAuthVariableOverride 使用UID到限制调用者的权限.
  4. 使用新选项初始化App对象(名为用户")的新非默认实例.现在,可以使用此 App对象同时遵守针对该用户的安全规则.
  5. 将Admin SDK与userApp一起使用,以对某些保护路径进行数据库查询.
  6. 如果查询成功,请记住响应并发送给cleint.
  7. 如果由于安全原因查询失败,请记住一个错误响应以发送给客户端.
  8. 清理此Admin SDK实例.此代码采取所有预防措施,以确保在任何情况下都调用userApp.delete(). 别忘了这样做,否则随着更多用户访问此功能,您将泄漏内存.
  9. 实际发送回复.这将终止该功能.
  1. Verifies a Firebase Authentication ID token using the Admin SDK. The token comes from the query string (but you should use a better solution to transmit the token).
  2. Pulls the user's UID out of the decoded token.
  3. Makes a copy of the default Firebase init configuration object, then adds a property called databaseAuthVariableOverride to it, using the UID, to limit the privileges of the caller.
  4. Initializes a new non-default instance of an App object (named "user") with the new options. This App object can now be used to access the database while observing security rules in place for that user.
  5. The Admin SDK is used along with userApp to make a database query to some protect path.
  6. If the query was successful, remember the response to send to the cleint.
  7. If the query failed due to security rues, remember an error response to send to the client.
  8. Clean up this instance of the Admin SDK. This code takes all precautions to make sure userApp.delete() is called in all circumstances. Don't forget to do this, or you will leak memory as more users access this function.
  9. Actually send the response. This terminates the function.

这是一个工作功能:

const admin = require("firebase-admin")
admin.initializeApp()

exports.authorizedFetch = functions.https.onRequest((req, res) => {
    let userApp
    let response
    let isError = false

    const token = req.query['token']

    admin.auth().verifyIdToken(token)
    .then(decoded => {
        // Initialize a new instance of App using the Admin SDK, with limited access by the UID
        const uid = decoded.uid
        const options = Object.assign({}, functions.config().firebase)
        options.databaseAuthVariableOverride = { uid }
        userApp = admin.initializeApp(options, 'user')
        // Query the database with the new userApp configuration
        return admin.database(userApp).ref("/some/protected/path").once('value')
    })
    .then(snapshot => {
        // Database fetch was successful, return the user data
        response = snapshot.val()
        return null
    })
    .catch(error => {
        // Database fetch failed due to security rules, return an error
        console.error('error', error)
        isError = true
        response = error
        return null
    })
    .then(() => {
        // This is important to clean up, returns a promise
        if (userApp) {
            return userApp.delete()
        }
        else {
            return null
        }
    })
    .then(() => {
        // send the final response
        if (isError) {
            res.status(500)
        }
        res.send(response)
    })
    .catch(error => {
        console.error('final error', error)
    })
})

同样,请注意在所有情况下均应调用userApp.delete(),以避免泄漏App实例.如果您想给每个新App分配一个基于用户的唯一名称,那不是一个好主意,因为随着新用户不断访问此功能,您仍然会用光内存.为了安全起见,请在每次通话时对其进行清理.

Again, note that userApp.delete() should be called in all circumstances to avoid leaking instances of App. If you had the idea to instead give each new App a unique name based on the user, that's not a good idea, because you can still run out of memory as new users keep accessing this function. Clean it up with each call to be safe.

还请注意,在发送响应之前,应在之前调用userApp.delete(),因为发送响应会终止该函数,并且您不希望由于任何原因中断清除.

Also note that userApp.delete() should be called before the response is sent, because sending a response terminates the function, and you don't want to have the cleanup interrupted for any reason.

这篇关于如何使用经过身份验证的ID令牌和数据库规则保护Firebase Cloud Function HTTP端点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆