Я использую ESP32 для загрузки изображений в хранилище Firebase, но через базовый JSON API Google Cloud Storage. Итак, я аутентифицируюсь как пользователь с помощью Firebase Rest API, а затем получаю токен идентификатора, чтобы использовать его для загрузки в хранилище.
Но я получаю сообщение об ошибке 401 Unauthorized при использовании этого токена идентификатора. Однако прямая замена токена ID на токен OAuth2.0 из Playground с областью действия https://www.googleapis.com/auth/devstorage.read_write
работает нормально; Я вижу, как изображения появляются в консоли Firebase.
Я видел этот вопрос, где Даг упоминает функциональность, которую я пытаюсь получить, но явно имею ошибку.
Мой код выглядит следующим образом:
#include "Arduino.h"
#include "globalVars.h"
#include "esp_camera.h"
#include <ArduinoJson.h>
#include <HTTPClient.h>
void checkMotion()
{
delay(10000);
camera_fb_t *fb = esp_camera_fb_get();
uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
uint8_t *jpeg_buf = (uint8_t *)ps_malloc(fbLen);
frame2jpg(fb, 2, &jpeg_buf, &fbLen);
long currTime = millis();
HTTPClient storageClient;
String STORAGE_UPLOAD_PATH = NEW_OBJECT_BASE_PATH + String(currTime) + ".jpeg";
storageClient.begin(STORAGE_UPLOAD_PATH);
Serial.print("uploading to : ");
Serial.println(STORAGE_UPLOAD_PATH);
// Using the ID Token from Auth--doesn't work
Serial.println(idToken); // successfully prints it out
String bearerString = String("Bearer ") + String(idToken);
storageClient.addHeader("Authorization", bearerString);
// Using Playground token instead, and commenting the above--works!
// storageClient.addHeader("Authorization", "Bearer MY_PLAYGROUND_TOKEN_IS_HERE");
// Content type
storageClient.addHeader("Content-Type", "image/jpeg");
storageClient.addHeader("Content-Length", String(fbLen));
int uploadResponseCode = storageClient.POST(jpeg_buf, fbLen);
Serial.print("Response code: ");
Serial.println(String(uploadResponseCode));
String uploadResponseRaw = storageClient.getString();
Serial.println("Received response:" + uploadResponseRaw);
const size_t responseCapacity = JSON_OBJECT_SIZE(100);
StaticJsonDocument<responseCapacity> dUploadResponse;
DeserializationError deserializeResult = deserializeJson(dUploadResponse, uploadResponseRaw);
Serial.println(deserializeResult.c_str());
storageClient.end();
free(jpeg_buf);
}
При использовании idToken я получаю ответ:
{
"error": {
"code": 401,
"message": "Invalid Credentials",
"errors": [
{
"message": "Invalid Credentials",
"domain": "global",
"reason": "authError",
"locationType": "header",
"location": "Authorization"
}
]
}
}
Во время тестирования я даже установил правила Firebase Storage, чтобы просто разрешить все:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if true;
}
}
}
Что мне не хватает? Заранее спасибо.
Токены Firebase ID можно использовать только через Firebase SDK. Затем серверные части Firebase выполняют проверки контроля доступа к токену ID в соответствии с правилами безопасности.
Доступ к облачному хранилищу через API GCP обходит серверы Firebase и правила безопасности и по этой причине не может быть выполнен с помощью токена Firebase ID. Вместо этого вам придется использовать токен OAuth 2.