I am trying to get gmail contacts using Google contacts api. For this i am using OAuth 2.0. For this i read their guide for using OAuth 2.0 here. Broadly i followed these steps
Register my app with google and get a client id and client secret and registered my redirect uri with them
now i first created a file called sample.php on which if the user clicks on get contacts he is redirected to google confirmation page
now google asks for confirmation and if the user agrees to provide its contact details then he is redirected to the redirect uri with a code.
now i extract the code and make a post request to get the OAuth token and if i get the token i make a request for the contacts.
The code for the sample.php looks like this
<?php
$client_id="my client id";
$redirect_uri="http://localhost/htdocs/contacts/redirect.php";
echo <<<doc
<html>
<body>
<a href="http://accounts.google.com/o/oauth2/auth?client_id=$client_id&redirect_uri=$redirect_uri&scope=https://www.google.com/m8/feeds/&response_type=code">
get contacts
</a>
doc;
echo <<<doc
</body>
</html>
doc;
?>
the code for the redirect.php looks like this
<?php
$client_id="my client id";
$client_sec="my client secret ";
$redirect_uri="http://localhost/htdocs/contacts/redirect.php";
$code=$_GET['code'];
$post="code=$code&client_id=$client_id&client_secret=$client_sec&redirect_uri=$redirect_uri&grant_type=authorization_code";
$post=urlencode($post);
//the following curl request is made to get the authorization token
$ch=curl_init();
$url="https://accounts.google.com/o/oauth2/token";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_AUTOREFERER,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$json=curl_exec($ch);
curl_close($ch);
echo $json; // this is showing Required parameter is missing: grant_type Error 400
$res=json_decode($json,true);
print_r($res); // this is just for debugging
$token=$res['access_token'];
echo $token; // this is just for debugging
$url="https://www.google.com/m8/feeds/contacts/default/full?oauth_token=$token";
//the following curl request is made to get the contacts
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_AUTOREFERER,1);
$xml=curl_exec($ch);
echo $xml;
curl_close($ch);
$dom= new DOMDocument();
$dom->loadXML($xml);
$xpath=new DOMXPath($dom);
$path='//gd:email';
$nodes=$xpath->query($path);
echo $nodes->length."<br />";
foreach($nodes as $node)
{
$email=$node->attributes->getNamedItem('address')->nodeValue;
echo $email."<br />";
}
?>
now the problem is that step 4 fails. It goes well till the confirmation step and when i click Allow access i am redirected to my redirect uri but its saying
Required parameter is missing: grant_type Error 400
now i dont understand this because i am providing the grant_type parameter. i looked in firebug and found out that a post request is being made but not the one which i intended. the post request that is being made is this
https://accounts.google.com/o/oauth2/approval?xsrfsign=AC9jObYAAAAATkfm3uvx0sfsW7WVmB_FeRqVPLjDcTLz and the status says 302 moved Temporarily. I dont understand whats going on. have they changed something in the OAuth workflow? Need some help
Edit
As suggested bu Ikke i removed the space before grant_type and it worked. Now i can get the access token but still i am unable to get the contacts.(i get an error as Empty string supplied as input in htdocs\contacts\redirect.php on line 35 and line 35 refers to $dom->loadXML($xml); so it seems that the get request is not being made) Moreover i am not able to see the post request being made in firebug (but surely its being made because i get the access token as the response). i also dont see the get request in firebug which i make after post request whats wrong?
Update:
the problem was that the request was on https and i was not using the appropriate headers for https. I used the correct headers and it worked.Problem solved? Maybe. Because i still dont understand why i am unable to see those get and post requests in firebug's' net` tab
There is a space between the & and the grant_type. That could cause google not to recognize the parameter.
"Because i still dont understand why i am unable to see those get and post requests in firebug's'net` tab"
I assume since you are requesting stuff with curl, it has nothing to do with firefox, since curl is a server-side library, therefore POSTs made by curl do not go through browser and firebug cannot see them.
You're passing an already urlencoded string to PHP's urlencode():
$post="code=$code&client_id=$client_id&client_secret=$client_sec&redirect_uri=$redirect_uri&grant_type=authorization_code";
$post=urlencode($post);
This messes up the value, Google's server can't properly parse it and therefore reports a missing parameter. Remove the $post=urlencode($post); line and see if it works better.
Related
I am trying to list files from google drive folder.
If I use jquery I can successfully get my results:
var url = "https://www.googleapis.com/drive/v3/files?q='" + FOLDER_ID + "'+in+parents&key=" + API_KEY;
$.ajax({
url: url,
dataType: "jsonp"
}).done(function(response) {
//I get my results successfully
});
However I would like to get this results with php, but when I run this:
$url = 'https://www.googleapis.com/drive/v3/files?q='.$FOLDER_ID.'+in+parents&key='.$API_KEY;
$content = file_get_contents($url);
$response = json_decode($content, true);
echo json_encode($response);
exit;
I get an error:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden
If I run this in browser:
https://www.googleapis.com/drive/v3/files?q={FOLDER_ID}+in+parents&key={API_KEY}
I get:
The request did not specify any referer. Please ensure that the client is sending referer or use the API Console to remove the referer restrictions.
I have set up referrers for my website and localhost in google developers console.
Can someone explain me what is the difference between jquery and php call and why does php call fails?
It's either the headers or the cookies.
When you conduct the request using jQuery, the user agent, IP and extra headers of the user are sent to Google, as well as the user's cookies (which allow the user to stay logged in). When you do it using PHP this data is missing because you, the server, becomes the one who sends the data, not the user, nor the user's browser.
It might be that Google blocks requests with invalid user-agents as a first line of defense, or that you need to be logged in.
Try conducting the same jQuery AJAX request while you're logged out. If it didn't work, you know your problem.
Otherwise, you need to alter the headers. Take a look at this: PHP file_get_contents() and setting request headers. Of course, you'll need to do some trial-and-error to figure out which missing header allows the request to go through.
Regarding the referrer, jQuery works because the referrer header is set as the page you're currently on. When you go to the page directly there's no referrer header. PHP requests made using file_get_contents have no referrer because it doesn't make much sense for them to have any.
I am currently developing a website which requires an API call to a social plugin website to obtain a user token. With the user token, I can call the website's login window and have the user log in with his/her login credentials to allow my app to obtain the required data.
When 1) I make the API call to the website, 2) it returns the URL with a user token in XML as shown below:
1)
Login
2)
<?xml version="1.0" encoding="UTF-8"?>
-<auth_token> <url>http://xxxxx.net/api/start_auth?token=7x1x81xfxxxxx5bxxxx3dx45trsda</url> <token>7x1x81xfxxxxx5bxxxx3dx45trsda</token> </auth_token>
However, I am relatively new to PHP and not sure what will be the right approach to handle this XML returned, and to redirect the website to "http://xxxxx.net/api/start_auth?token=7x1x81xfxxxxx5bxxxx3dx45trsda". Once redirected, I can have user to log in and get the information I needed.
I have tried using curl method as shown below, but I am not familiar with parsing the result of curl_exe() and redirecting the site using the parsed value. I have not been able to get it working yet, but I think there should be more php native way to handle the returned XML and to use that serialized XML objects for redirecting the website.
<?php $ch = curl_init(); ?>
<?php curl_setopt($ch, CURLOPT_URL, "http://xxxxx.net/api/get_auth_url.xml?akey=$myAppKey"); ?>
<?php curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ?>
<?php $store = curl_exec($ch); ?>
<?php curl_close($ch); ?>
Any feedback will be much appreciated.
WL
i'd give SimpleXMLElement a shot once you've got your XML String (for which I'd also use curl_exec(), by the way) ...
$authTokenXml = new SimpleXMLElement( $store );
$authUrl = $authTokenXml->url
and now you can use $authUrl in any way you like, e.g. sending a http redirect header:
header('Location: ' . $authUrl);
or with another CURL.
Hope that helps!
(btw. you don't need the <?php-Tags in every line. It starts a php block, actually)
Start with the SimpleXML documentation
We are developing a web app that enables the end user to place a bit of code on their webpage, so that anyone who visits their page will see a little pop up button on the edge of the browser window. When clicked, it opens a small panel where they can enter a telephone number for the website owner to call them back.
I am running up against a security issue. I am attempting to use server side include to place the button on the client's website. However, because this included site is on a different domain than the client's website, it is not allowed.
I have tried these two methods that I got from online forums, neither of which worked for me.
Use the file_get_contents handler, like this;
$includeFile =
file_get_contents("http://bizzocall.com/subdomains/dev/httpdocs/slideouttesttopDATA.php");
echo $includeFile;
ERRORĀ failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found.
Use curl, like this:
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$feed = 'http://bizzocall.com/subdomains/dev/httpdocs/slideouttesttopDATA.php';
$bizzobtn = curl($feed);
echo $bizzobtn;
This didn't work either.
ERROR The requested URL /subdomains/dev/httpdocs/slideouttesttopDATA.php was not found on this server.
This looks like its truncating the bizzocall.com/ off of the url. Perhaps If I knew how to write this chunk of code correctly,this would work.
Any help here would be welcome!
The 404 error is coming from the remote server, not your own. Try to reach that URL - You'll get the same 404.
When I visit http://bizzocall.com/subdomains/dev/httpdocs/slideouttesttopDATA.php, I get the following:
Therefore, the issue is that you're using the wrong URL. Your code is sound, however.
Your curl code is working fine, the problem is the URL isn't found.
Put it in your browser to see.
If you own bizzocall.com, you'll want to put slideouttesttopDATA.php in a web accessible area, then you'll be able to access it with curl.
Visit your link a browser and you'll see that the resource you're trying to request clearly doesn't exist. More info on the HTTP 404 status code found here: http://en.wikipedia.org/wiki/HTTP_404.
Perhaps it should be http://dev.bizzocall.com/slideouttesttopDATA.php as your URL does not work when pasted into a browser...
I am using Facebook's Facebook Query Language (FQL) to get information on a user once I already know his user id. When I enter the following URL into Firefox, it returns the correct XML for the request:
http://api.facebook.com/method/fql.query?query=SELECT name FROM user WHERE uid= **'
Namely it returns the user's name.
Note: please don't suggest using Graph API as I will in fact be using FQL for things not implemented in Graph yet like networks, this is just a simple example.
BUT, when I go to the page on my website which executes the following PHP code:
$url = 'http://api.facebook.com/method/fql.query?query=SELECT name FROM user WHERE uid=**********';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo($response);
I see:
Method Not Implemented
Invalid method in request
This shouldn't be an authentication problem either, name is something that is publicly available.
For more insight, when I enter any malformed FQL request, the PHP page correctly returns an error XML, just as it would when you enter the URL in Firefox. It is only when I enter a CORRECTLY FORMED FQL request that it differs from what I see in Firefox, namely, it gives the error above, which is not even XML.
Any ideas? Thanks.
Are you properly encoding the query parameters? Try something like:
$query = 'SELECT name FROM user WHERE uid=**********';
$url = 'http://api.facebook.com/method/fql.query?query=' . rawurlencode($query);
Or you can use the Facebook PHP SDK which automatically does this for you.
I do not know much about the error messages associated with FQL but the SQL query is supposed to be url escaped (urlencode - http://php.net/manual/en/function.urlencode.php). Perhaps this could help your error.
Actually, it's gotten so messy that I'm not even sure curl is the culprit. So, here's the php:
$creds = array(
'pw' => "xxxx",
'login' => "user"
);
$login_url = "https://www.example.net/login-form"; //action value in real form.
$loginpage = curl_init();
curl_setopt($loginpage, CURLOPT_HEADER, 1);
curl_setopt($loginpage, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($loginpage, CURLOPT_URL, $login_url);
curl_setopt($loginpage, CURLOPT_POST, 1);
curl_setopt($loginpage, CURLOPT_POSTFIELDS, $creds);
$response = curl_exec($loginpage);
echo $response;
I get the headers (which match the headers of a normal, successful request), followed by the login page (I'm guessing curl captured this due to a redirect) which has an error to the effect of "Bad contact type".
I thought the problem was that the request had the host set to the requesting server, not the remote server, but then I noticed (in Firebug), that the request is sent as GET, not POST.
If I copy the login site's form, strip it down to just the form elements with values, and put the full URL for the action, it works just great. So I would think this isn't a security issue where the login request has to originate on the same server, etc. (I even get rid of the empty hidden values and all of the JS which set some of the other cookies).
Then again, I get confused pretty quickly.
Any ideas why it's showing up as GET, or why it's not working, for that matter?
When troubleshooting the entire class of PHP-cURL-related problems, you simply have to turn on CURLOPT_VERBOSE and give CURLOPT_STDERR a file handle.
tail -f your file, compare the headers and response to the ones you see in Firebug, and the problem should become clear.
The request is made from the server, and will not show up in Firebug. (You probably confused it with another request by your browser). Use wireshark to find out what really happens. You are not setting CURLOPT_FOLLOWLOCATION; redirects should not be followed.
Summarizing: Guess less, post more. Link to a pcap dump, and we will be able to tell exactly what you're doing wrong; or post the exact output of the php script, and we might.
The shown code does a multipart formpost (since you pass a hash array to the POSTFIELDS option), which probably is not what the target server expects.
try throwing in a print_r(curl_getinfo($loginpage)) at the end, see what the header data it sent back as.
also, if your trying to fake that your logging in from their site, your going to want to make sure your sending the correct referrer with your post, so that they "think" you were on the website when you sent it.