javascript - 如何使用经过身份验证的 id token 和数据库规则保护 Firebase Cloud Function HTTP 端点?

标签 javascript firebase firebase-realtime-database firebase-authentication google-cloud-functions

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

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

最佳答案

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

  • 使用 Admin SDK 验证 Firebase 身份验证 ID token 。 token 来自查询字符串(但您应该 use a better solution 来传输 token )。
  • 从解码的 token 中提取用户的 UID。
  • 复制默认的 Firebase 初始化配置对象,然后添加一个名为 databaseAuthVariableOverride 的属性给它,使用 UID,到 limit the privileges of the caller .
  • 使用新选项初始化 App 对象(名为“用户”)的新非默认实例。这个App object现在可以用于访问数据库,同时遵守为该用户制定的安全规则。
  • Admin SDK 与 userApp 一起使用对某个保护路径进行数据库查询。
  • 如果查询成功,请记住发送给客户端的响应。
  • 如果查询由于安全原因而失败,请记住要发送给客户端的错误响应。
  • 清理此 Admin SDK 实例。此代码采取一切预防措施以确保 userApp.delete()在所有情况下都被调用。 不要忘记这样做,否则会随着更多用户访问此功能而导致内存泄漏。
  • 实际发送响应。这将终止函数。

  • 这是一个工作函数:
    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 实例。如果您的想法是根据用户为每个新应用程序赋予一个唯一的名称,这不是一个好主意,因为当新用户继续访问此功能时,您仍然可能会耗尽内存。每次通话都要清理干净以确保安全。

    另请注意 userApp.delete()应该叫 之前 响应已发送,因为发送响应会终止函数,并且您不希望清理因任何原因而中断。

    关于javascript - 如何使用经过身份验证的 id token 和数据库规则保护 Firebase Cloud Function HTTP 端点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48575730/

    相关文章:

    Javascript - 从列表返回值

    android - 如何使用 Firebase ML Kit 在图像中查找标记?

    android - 如何使用 firebase ML Kit 识别条形码?

    javascript - createUserWithEmailAndPassword后如何设置用户数据(web)

    java - 自动更新类内的共享首选项

    java - 从 Firebase 实时数据库检索特定数据的最快方法?

    javascript - DOM 元素上的空样式属性 : JavaScript

    javascript - 如何将 Javascript 变量分配给另一个变量的相同值

    javascript - Angularjs ng-view 不显示数据

    android - Firebase ML Kit : "Internal Error" Exception, 但良好的输入和良好的配置