parse-community/parse-php-sdk

REST API not working with PHP

MrMegamind opened this issue ยท 13 comments

I am integrating REST API using PHP but I always get Unauthorized error.

I have verified the credentials and they appear perfectly fine

PHP Code:

	ParseClient::initialize( $this->parse_app_id, $this->parse_rest_key, $this->parse_master_key);
	ParseClient::setServerURL('https://parseapi.back4app.com', '/');

	$health = ParseClient::getServerHealth();
	if($health['status'] === 200) {
	    echo "everything looks good!";
	}
	print_r($health);

This is verbos output of cURL

  • Hostname parseapi.back4app.com was found in DNS cache
  • Trying 52.6.211.84...
  • TCP_NODELAY set
  • Connected to parseapi.back4app.com (52.6.211.84) port 443 (#0)
  • ALPN, offering http/1.1
  • Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@strength
  • successfully set certificate verify locations:
  • CAfile: /etc/pki/tls/certs/ca-bundle.crt
    CApath: none
  • SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
  • ALPN, server did not agree to a protocol
  • Server certificate:
  • subject: CN=*.back4app.com
  • start date: Oct 23 00:00:00 2017 GMT
  • expire date: Nov 23 12:00:00 2018 GMT
  • subjectAltName: host "parseapi.back4app.com" matched cert's "*.back4app.com"
  • issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
  • SSL certificate verify ok.

GET /health HTTP/1.1
Host: parseapi.back4app.com
Accept: /
X-Parse-REST-API-Key: pR8VQMjGxPFYo5EdVTcr0UspwCQTuKhHWAMbObfc

< HTTP/1.1 401 Unauthorized
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, X-Application-ID, X-Access-Token, X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Job-Status-Id, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-CSRF-Token
< Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
< Access-Control-Allow-Origin: *
< Content-Type: application/json; charset=utf-8
< Date: Fri, 28 Sep 2018 12:57:05 GMT
< ETag: W/"18-gH7/fIZxPCVRh6TuPVNAgHt/40I"
< Server: nginx
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-Powered-By: Express
< X-XSS-Protection: 1; mode=block;
< Content-Length: 24
< Connection: keep-alive
<

  • Connection #0 to host parseapi.back4app.com left intact
    Array ( [status] => 401 [response] => )

@MrMegamind this is a configuration issue, not an issue with the sdk. I think that the ParseClient::setServerURL might be incorrect? You may also be able to get support from back4app?

I added following code in ParseCurl.php file at around line 48

	$this->setOption(CURLOPT_HTTPHEADER,array("X-Parse-Application-Id: xxx", "X-Parse-REST-API-Key: xxx"));

and then it started working, which means the SDK has issues of not setting the headers when we initialize

Do you mean around line 480?

Can you step through ParseClient::_request() and see why the header isn't getting set?

Can you double verify that $this->parse_app_id, $this->parse_rest_key, $this->parse_master_key are definately set in your initialization?

What version of the SDK are you using?

I'm gonna close this for now. We can re-open if necessary.

I'm facing the same issue. I'm using back4app and here is my initialization code.

<?php

require 'vendor/autoload.php';
use Parse\ParseClient;


$app_id = "FAxjcqLe7t2zxeOtxxxxxxxxxxx";
$rest_key = "FuiOPvWei8Scwxxxxxxxxxxxxxxxxx";
$master_key = 'IdN0psRjfv9bJNPxxxxxxxxxxxxxxx";

ParseClient::initialize( $app_id, $rest_key, $master_key );
ParseClient::setServerURL('https://parseapi.back4app.com/','/');

$health = ParseClient::getServerHealth();
echo("health check started..<br>");

echo(json_encode($health));

if($health['status'] === 200) {
    // everything looks good!
    echo("<br>health is good");
}else{
    echo("<br>health is not good");
}

echo("<br>health finished..");
?>

here is the output i'm getting.

health check started..
{"status":401,"response":{"error":"unauthorized"}}
health is not good
health finished..

I don't know what should be the mount point for parse in back4app. But I've checked the sdk it allows to mount at root so I passed the "/", here is the evidence.

public static function setServerURL($serverURL, $mountPath)
    {
        if (!$serverURL) {
            throw new Exception('Invalid Server URL.');
        }
        if (!$mountPath) {
            throw new Exception('Invalid Mount Path.');
        }

        self::$serverURL = rtrim($serverURL, '/');
        self::$mountPath = trim($mountPath, '/') . '/';

        // check if mount path is root
        if (self::$mountPath == "/") {
            // root path should have no mount path
            self::$mountPath = "";
        }
    }

It checks at the end for the mount point as root.
I'm using PHP 7.2, and installed sdk from composer.

Note : curl is working fine using php and back4app. The problem is in parse sdk.

For those who want workaround is what @MrMegamind said to do.
Add these lines inside the exec() function of ParseCurl.php, before the curl_exec() function.

curl_setopt($this->curl, CURLOPT_HTTPHEADER, array(
            "X-Parse-Application-Id: replacewithyourkey",
            "X-Parse-REST-API-Key: replacewithyourkey",
            ));

Now the function will look like this.

public function exec()
    {
        if (!isset($this->curl)) {
            throw new ParseException('You must call ParseCurl::init first');
        }
      curl_setopt($this->curl, CURLOPT_HTTPHEADER, array(
            "X-Parse-Application-Id: replacewithyourkey",
            "X-Parse-REST-API-Key: replacewithyourkey",
            ));
        return curl_exec($this->curl);
   }
   

@parasthekoder Does query and saving objects work instead of the health endpoint?

Nope, saving objects doesn't work, and queries too. Everything fails with exception unauthorized because these headers aren't included in curl i.e., X-Parse-Application-Id, X-Parse-REST-API-Key (if provided in initialization ) and X-Parse-Master-Key. I've also faced "Invalid field name" error because 'Content-Type: application/json' was also not added in the headers.

Sorry I am unable to replicate the issue. Can you debug this?

I find it weird that ParseClient::getServerHealth(); didn't work for you. /health endpoint is public and doesn't require keys / headers to ping.

After having so many issues with back4app and php. I've installed parse-server locally and found that these headers are included in the latest version and fixed my problem. This issue is related with the back4app api.
Where as changing the parse server version doesn't work actually there. I think this button is broken.

back4app

Conclusion : I don't know what time it takes for back4app to change parse version. But I've learnt that don't post issue when using third party APIs.

It never hurts to post issues. You never know what you might find ๐Ÿ‘

@MrMegamind Back4App needs at least a custom subdomain (your-app.back4app.io) or appId key to send requests to your app. Any request without one of those methods will return unauthorized.
The method getServerHealth on PHP SDK doesn't send the appId and you aren't using a subdomain, so it's returning unauthorized. All other methods and functions send at least the appId.
So, try to create a subdomain on Server Settings -> Web Hosting + Live Query and use it as your endpoint on setServerURL.
After that, try to use getServerHealth.

@paivaric Thank you for suggestion, I gave up a long ago but this might help others facing similar issues. I was only able to solve all the requests by adding custom headers. @parasthekoder thanks for clarifying how to use the workaround. Happy coding