I've successfully authenticated and obtained the id token, but when attempting to use it to perform a GET or PATCH request on a Firestore document, I receive the following error as an HTTP response:
Code: Select all
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
E (5443) HTTP_CLIENT: This authentication method is not supported: Bearer realm="https://accounts.google.com/"
You can refer to the Firebase documentation for more details:
https://firebase.google.com/docs/reference/rest/auth
https://firebase.google.com/docs/firestore/use-rest-api
https://firebase.google.com/docs/firest ... uments/get
https://firebase.google.com/docs/firest ... ents/patch
These HTTP requests function correctly when tested in Postman.
Code: Select all
AUTH GET ID_TOKEN
Method: POST
URL:https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword
keys: key -> value:{firebase Web API Key}
Body:{"email":"","password":"","returnSecureToken":true}
GET FIRESTORE DOCUMENT IFNO
Method: GET
URL:https://firestore.googleapis.com/v1/projects/esp-idf-test/databases/(default)/documents/test/testDoc (test is the collection testDoc is the Document)
keys: NULL
Body: NULL
Authorization: type->Bearer Token Token->{The token_id you got from the AUTH GET ID_TOKEN}
PATCH FIRESTORE DOCUMENT IFNO
Method: PATCH
URL:https://firestore.googleapis.com/v1/projects/esp-idf-test/databases/(default)/documents/test/testDoc (test is the collection testDoc is the Document)
keys: updateMask.fieldPaths -> value:testString(the name of the string var inside the document testDoc)
Body: {
"fields": {
"testString": {
"stringValue": "helloWorld"
}
}
}
Authorization: type->Bearer Token Token->{The token_id you got from the AUTH GET ID_TOKEN}
Code: Select all
#include "http_requests.h"
char receivedData[4096];
char idToken[1950];
char client2Header[2000];
bool showReceivedData = false;
// Event handler function for HTTP client events
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
printf("HTTP_EVENT_ERROR\n");
break;
case HTTP_EVENT_ON_CONNECTED:
printf("HTTP_EVENT_ON_CONNECTED\n");
break;
case HTTP_EVENT_HEADER_SENT:
printf("HTTP_EVENT_HEADER_SENT\n");
break;
case HTTP_EVENT_ON_HEADER:
printf("HTTP_EVENT_ON_HEADER\n");
break;
case HTTP_EVENT_ON_DATA:
// Find the first occurrence of '}'
const char *end_ptr = strchr((char *)evt->data, '}');
if (end_ptr != NULL)
{
// Calculate the length until the '}' character
size_t length = end_ptr - (char *)evt->data + 1; // Include '}' in the length
// Concatenate only until the '}' character
strncat(receivedData, (char *)evt->data, length);
printf("end_ptr is: %p evt-data is : %p length is :%d \n", end_ptr, (char *)evt->data, length);
}
else
{
// If '}' is not found, just concatenate the entire data
strncat(receivedData, (char *)evt->data, evt->data_len - 1);
}
if (showReceivedData == true){
printf("evt-data is %s", (char *)evt->data);
}
break;
case HTTP_EVENT_ON_FINISH:
printf("HTTP_EVENT_ON_FINISH\n");
break;
case HTTP_EVENT_DISCONNECTED:
printf("HTTP_EVENT_DISCONNECTED\n");
break;
case HTTP_EVENT_REDIRECT:
printf("HTTP_EVENT_REDIRECT\n");
break;
}
return ESP_OK; // Return OK status
}
esp_err_t firestore_get_document(const char *id_token)
{
esp_http_client_config_t config = {
.url = "https://firestore.googleapis.com/v1/projects/esp-idf-test/databases/(default)/documents/test/testDoc",
.method = HTTP_METHOD_GET,
.event_handler = _http_event_handler,
.transport_type = HTTP_TRANSPORT_OVER_SSL,
.crt_bundle_attach = esp_crt_bundle_attach,
.buffer_size = 2048,
.buffer_size_tx = 4096, // Adjust buffer size as needed
};
esp_http_client_handle_t client2 = esp_http_client_init(&config);
showReceivedData = true;
// Authentication: Bearer
strlcpy(client2Header, "Bearer ", sizeof(client2Header));
strlcat(client2Header, id_token, sizeof(client2Header));
printf("Header data: %s\n", client2Header);
// Set headers
esp_http_client_set_header(client2, "Authorization", client2Header);
if (!client2)
{
return ESP_FAIL;
}
memset(receivedData, '\0', sizeof(receivedData));
// Perform HTTP request
esp_err_t err2 = esp_http_client_perform(client2);
if (err2 != ESP_OK)
{
printf("problem \n");
}
// Clean up
esp_http_client_cleanup(client2);
return err2;
}
// Function to authenticate with Firebase using email and password
void firebase_authenticate(const char *email, const char *password, const char *api_key)
{
// Configure HTTP client
esp_http_client_config_t config = {
.url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword",
.method = HTTP_METHOD_POST,
.event_handler = _http_event_handler,
.user_data = NULL,
.auth_type = HTTP_AUTH_TYPE_BASIC,
.transport_type = HTTP_TRANSPORT_OVER_SSL,
.crt_bundle_attach = esp_crt_bundle_attach,
};
// Construct JSON payload for authentication
char post_data[150];
snprintf(post_data, sizeof(post_data), "{\"email\":\"%s\",\"password\":\"%s\",\"returnSecureToken\":true}", email, password);
printf("%s \n", post_data);
// Initialize HTTP client
esp_http_client_handle_t client = esp_http_client_init(&config);
// Set content type header
esp_http_client_set_header(client, "Content-Type", "application/json");
char url_with_query[256];
snprintf(url_with_query, sizeof(url_with_query), "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=%s", api_key);
// Set the URL for the HTTP request
esp_http_client_set_url(client, url_with_query);
// Set post data
esp_http_client_set_post_field(client, post_data, strlen(post_data));
printf("\nThe final url with query in order to sign in with email and pass is: \n %s \n", url_with_query);
char *clientHeader;
esp_http_client_get_header(client, "Content-Type", &clientHeader);
printf("The header in order to sign in with email and pass is: \n %s \n", clientHeader);
char *clientPostData;
esp_http_client_get_post_field(client, &clientPostData);
printf("The body in order to sign in with email and pass is: \n %s \n\n", clientPostData);
// Perform HTTP POST request
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
printf("we are here\n");
// Check if response code is 200 OK
if (esp_http_client_get_status_code(client) == 200)
{
printf("Response code of firebase sign in is OK \n");
cJSON *json = cJSON_Parse(receivedData);
if (json != NULL)
{
cJSON *id_token = cJSON_GetObjectItem(json, "idToken");
if (id_token != NULL)
{
strncpy(idToken, id_token->valuestring, sizeof(idToken));
size_t idToken_len = strlen(idToken);
idToken[idToken_len] = '\0'; // Null-terminate the string again
printf("ID Token: %s\n", idToken);
}
cJSON_Delete(json);
}
}
}
else
{
printf("Something went wrong with client perform");
}
// Clean up HTTP client
esp_http_client_cleanup(client);
printf("calling the HTTP Request \n");
firestore_get_document(idToken);
}