I'm using REST API in a PHP project to send the data to Firestore DB through curl (PHP curl).
I'm struggling in understanding how to setup an authentication rule for a "service" and the suggested approach through Google authorization looks overkilling to me.
My data must be readable by ALL but writable just by my PHP server.
So far I could ensure that a writing operation could happen only if in the dataset sent a specific code is provided (auth=123):
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.resource.data.auth==123
//request.auth.uid != null;
}
}
}
Problem is that, as everybody can read the data, it's very easy to find this field (auth) and to know that 123 is the code.
Would be possible any of the two:
Send headers (or other not recorded into DB data) and perform a rule check against that instead of the data fields?
Otherwise (less preferred) would be possible to hide ONLY the field "auth" to the users?
I know option 2 is not possible in principle but it might be worked around somehow even if I don't know how.
While I understand this is not the best approach, it would be more than enough to secure my application.
EDIT
Probably the simplest cleanest solution would be to create an user in Firestore db with a pair email/password and use that in the PHP curl request
I think I need to issue a curl request following this:
https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-email-password
And then issuing the upload of the data through another PHP curl using as auth the token received in the first request
I feel like it's the right path but.... I get stuck at the first request with
404. That’s an error.
The requested URL /identitytoolkit/v3/relyingparty/verifyPassword?key=myapiket was not found on this server. That’s all we know.
I feel like I badly shaped my curl request... any suggestion on how to handle properly the payload?
SOLUTION
See my answer below with steps and PHP code
SOLUTION
Ok, I found the solution to achieve a simple but effective authentication when using Firebase Firestore REST API used through curl PHP.
1- Create a Firebase project
2- In my case I need everybody to be able to read data and only one user to write data. So in "Database/Rules" I've put:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
3- In "Authentication/Sign-In Method" enable "Email/Password" as Sign-In Provider
4- In "Authentication/Users", add a user and provide a pair "email/password"
5- Identify your project API key which can be found in "Project Overview/Settings/General/Web API Key"
6- Issue a curl request to obtain a tokenId which is validate through username and password and use this token to validate the Firestore action. Code below:
<?php
// 1) Retrieve Authorization TOKEN
// https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-email-password
$firestore_key = "MY_KEY";
$url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword";
$postfields = array(
"email" => '[email protected]',
"password" => 'password123456',
"returnSecureToken" => true
);
$datapost = json_encode($postfields);
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array('Content-Type: application/json'),
CURLOPT_URL => $url . '?key='.$firestore_key,
CURLOPT_USERAGENT => 'cURL',
CURLOPT_POSTFIELDS => $datapost
));
$response = curl_exec( $curl );
curl_close( $curl );
$responsJson=json_decode($response,true);
// 2) Add data
//https://medium.com/@aliuwahab/firestore-firebase-php-saving-data-to-a-firestore-database-using-php-curl-2921da3b0ed4
$ID=10000001;
$firestore_data = [
"status" => ["integerValue" => 1500]
];
$data = ["fields" => (object)$firestore_data];
// Possible *value options are:
// stringValue
// doubleValue
// integerValue
// booleanValue
// arrayValue
// bytesValue
// geoPointValue
// mapValue
// nullValue
// referenceValue
// timestampValue
$json = json_encode($data);
#Provide your firestore project ID Here
$project_id = "myspecific_project"; //found in "Database/Data"
#Provide your firestore documents group
$documents_group = "my_group";
// https://stackoverflow.com/questions/50866734/rest-api-firestore-authentication-with-id-token/50866783#50866783
$url = "https://firestore.googleapis.com/v1beta1/projects/$project_id/databases/(default)/documents/$documents_group/$ID/";
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array('Content-Type: application/json',
'Content-Length: ' . strlen($json),
'X-HTTP-Method-Override: PATCH',
'Authorization: Bearer '.$responsJson['idToken']
),
CURLOPT_URL => $url . '?key='.$firestore_key ,
CURLOPT_USERAGENT => 'cURL',
CURLOPT_POSTFIELDS => $json
));
$response = curl_exec( $curl );
curl_close( $curl );
// Show result
echo $response . "\n";
?>
NOTE: In the code I marked down links to information that helped me coming out with a working solution
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With