简单(和)肮脏的Firestore身份验证规则

时间:2019-02-21 13:29:12

标签: rest curl firebase-authentication google-cloud-firestore firebase-security-rules

我在PHP项目中使用REST API,通过curl(PHP curl)将数据发送到Firestore DB。

我正在努力了解如何为“服务”设置身份验证规则,而通过Google授权提出的建议方法对我来说显得过于刻板。

我的数据必须对所有人都可读,但只能由我的PHP服务器写入。

到目前为止,我可以确保只有在发送的数据集中提供了特定代码(auth = 123)时,才可以进行写操作:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.resource.data.auth==123
      //request.auth.uid != null;
    }
  }
}

问题在于,由于每个人都可以读取数据,因此很容易找到此字段(auth)并知道123是代码。

可能是以下两种情况中的任何一种:

  1. 发送标头(或其他未记录到DB数据中的标头),并根据规则而不是数据字段执行规则检查?

  2. 否则(较不受欢迎)可以仅向用户隐藏“ auth”字段吗?

我知道选项2原则上是不可能的,但是即使我不知道如何也可以解决该问题。

虽然我知道这不是最好的方法,但它足以保护我的应用程序。

编辑

最简单的解决方案可能是在Firestore数据库中创建一个具有一对电子邮件/密码的用户,并在PHP curl请求中使用该用户

我认为我需要在此之后发出curl请求:

https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-email-password

然后使用另一个请求中收到的令牌作为身份验证,通过另一个PHP curl发出数据上传

我觉得这是正确的道路,但是....我被第一个请求困住了

 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.

我觉得我对卷曲请求的处理方式不正确...关于如何正确处理有效载荷的任何建议?

解决方案

请参阅下面的步骤和PHP代码

2 个答案:

答案 0 :(得分:0)

无法随您的请求发送自定义标头。或更准确地说:这些标头在您的安全规则中不可用。参见In Firebase Firestore, is there any way to pass info to the Security Rules which is not part of the path?Accessing Cookies in Google Firestore RuleHow to let specific API to run write/read requests on firestore?

也无法通过安全规则隐藏文档的单个字段。用户完全可以访问文档,或者完全不能访问文档。参见Firestore: restricting child/field access with security rulesSecuring specific Document fields in Firestore

您唯一的真实选择是验证您的PHP脚本并将令牌传递给调用,然后确认它是您的服务器进行更改。

答案 1 :(得分:0)

解决方案

好吧,我找到了使用通过curl PHP使用的Firebase Firestore REST API时实现简单但有效身份验证的解决方案。

1-创建一个Firebase项目

2-以我为例,我需要每个人都能够读取数据,并且只有一个用户才能写入数据。因此,在“数据库/规则”中,我输入:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.uid != null;
    }
  }
}

3-在“身份验证/登录方法”中,启用“电子邮件/密码”作为登录提供程序

4-在“身份验证/用户”中,添加一个用户并提供一对“电子邮件/密码”

5-确定您的项目API密钥,可在“项目概述/设置/常规/ Web API密钥”中找到

6-发出curl请求以获得通过用户名和密码验证的tokenId,并使用此令牌来验证Firestore操作。下面的代码:

<?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@domain.com',
        "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";

?>

注意:在代码中,我标记了指向有助于我提出可行解决方案的信息的链接