使用 Firebase ID 令牌对 Firebase 存储进行身份验证 [英] Authenticate Firebase Storage with Firebase ID Token

本文介绍了使用 Firebase ID 令牌对 Firebase 存储进行身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望服务器端的凭据尽可能干净.因此,我使用 Firebase Auth Rest Api.从请求中,我获得了 Firebase ID 令牌,并使用此令牌向 Firebase 实时数据库发出请求,为 Authenticate Rest Request (Authenticate with an ID token)解释.

I want to have my server-side as clean of credentials as possible. For that reason, I authenticate myself with Firebase Auth using Firebase Auth Rest Api. From the request, I obtain the firebase ID Token and with this token, I make requests to Firebase Realtime Database as Authenticate Rest Request (Authenticate with an ID token) explains.

问题在于,当我尝试对 Firebase Storage 执行相同操作时 (Google Cloud存储请求端点) 我没有找到任何避免将凭据存储在服务器端的解决方案(例如,使用 Admin SDK 我可以写入或读取任何文件,但这意味着我的服务器未来可能会出现安全问题,因为我的凭据已暴露)尽管在 验证休息请求(使用 ID 令牌验证) 明确表示:当用户或设备使用 Firebase 身份验证登录时,Firebase 会创建一个相应的 ID 令牌来唯一标识他们并授予他们访问多个资源的权限,例如实时数据库和云存储."

The problem is that when I try to do the same with Firebase Storage (Google Cloud Storage Request Endpoints) I don´t find any solution avoiding credentials storing in server-side (for example, with Admin SDK I can write or read any file, but this means a possible future issue with security in my server because my credentials are exposed) despite in Authenticate Rest Request (Authenticate with an ID token) clearly says: "When a user or device signs in using Firebase Authentication, Firebase creates a corresponding ID token that uniquely identifies them and grants them access to several resources, such as Realtime Database and Cloud Storage."

问题是:如何像使用 Firebase 运行时数据库一样使用 Firebase ID 令牌来授权 Firebase Storage Api Rest 调用?

The question is: how can I use the Firebase ID Token to authorize Firebase Storage Api Rest calls as I did with Firebase Runtime Database?

谢谢.

推荐答案

我终于找到了我的答案的解决方案.解决方案是使用 Cloud Functions.

Finally I found a solution to my answer. The solution is to use Cloud Functions.

Cloud Functions 允许我们在作为我们 firebase 项目的一部分的 nodejs 环境中创建端点并使用 AdminSdk.使用这种方法,我们可以向该端点发送一个 http 请求,这会检查接收到的带有请求的 Token 是否有效,如果是,它会保存文件.

Cloud Functions allows us to create endPoints and to use AdminSdk in a nodejs enviroment which is part of our firebase project. With this approach we can send an http request to that endpoint, this checks if the received Token with the request is valid and if it is, it saves the file.

这是功能代码:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const path = require("path");
const os = require("os");
const fs = require("fs");
const Busboy = require("busboy");

// Follow instructions to set up admin credentials:
// https://firebase.google.com/docs/functions/local-emulator#set_up_admin_credentials_optional
admin.initializeApp({
  credential: admin.credential.cert(
    __dirname + "/path/to/cert.json"
  ),
  storageBucket: "bucket-name",
});

const express = require("express");
const app = express();

// Express middleware that validates Firebase ID Tokens passed in the Authorization HTTP header.
// The Firebase ID token needs to be passed as a Bearer token in the Authorization HTTP header like this:
// `Authorization: Bearer <Firebase ID Token>`.
// when decoded successfully, the ID Token content will be added as `req.user`.
const authenticate = async (req, res, next) => {
  if (
    !req.headers.authorization ||
    !req.headers.authorization.startsWith("Bearer ")
  ) {
    res.status(403).send("Unauthorized");
    return;
  }
  const idToken = req.headers.authorization.split("Bearer ")[1];
  try {
    const decodedIdToken = await admin.auth().verifyIdToken(idToken);
    req.user = decodedIdToken;
    next();
    return;
  } catch (e) {
    res.status(403).send("Unauthorized");
    return;
  }
};

app.use(authenticate);

// POST /api/messages
// Create a new message, get its sentiment using Google Cloud NLP,
// and categorize the sentiment before saving.
app.post("/test", async (req, res) => {
  const busboy = new Busboy({ headers: req.headers });
  const tmpdir = os.tmpdir();

  // This object will accumulate all the fields, keyed by their name
  const fields = {};

  // This object will accumulate all the uploaded files, keyed by their name.
  const uploads = {};

  // This code will process each non-file field in the form.
  busboy.on("field", (fieldname, val) => {
    // TODO(developer): Process submitted field values here
    console.log(`Processed field ${fieldname}: ${val}.`);
    fields[fieldname] = val;
  });

  const fileWrites = [];

  // This code will process each file uploaded.
  busboy.on("file", (fieldname, file, filename) => {
    // Note: os.tmpdir() points to an in-memory file system on GCF
    // Thus, any files in it must fit in the instance's memory.
    console.log(`Processed file ${filename}`);
    const filepath = path.join(tmpdir, filename);
    uploads[fieldname] = filepath;

    const writeStream = fs.createWriteStream(filepath);
    file.pipe(writeStream);

    // File was processed by Busboy; wait for it to be written.
    // Note: GCF may not persist saved files across invocations.
    // Persistent files must be kept in other locations
    // (such as Cloud Storage buckets).
    const promise = new Promise((resolve, reject) => {
      file.on("end", () => {
        writeStream.end();
      });
      writeStream.on("finish", resolve);
      writeStream.on("error", reject);
    });
    fileWrites.push(promise);
  });

  // Triggered once all uploaded files are processed by Busboy.
  // We still need to wait for the disk writes (saves) to complete.
  busboy.on("finish", async () => {
    await Promise.all(fileWrites);
   
    // Process saved files here
    for (const file in uploads) {
      admin.storage().bucket().upload(uploads[file], function(err, file) {
        if (err) {
          res.status(403).send("Error saving the file.");
        }
        res.status(201).send("Saved");
      });
    }
  });

  busboy.end(req.rawBody);
});

exports.api = functions.https.onRequest(app);

这篇关于使用 Firebase ID 令牌对 Firebase 存储进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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