I'm call the foursquare api with the userless access approach in php using curl.
The foursquare endpoint venues search is supposed to support userless access.
$city = urlencode($city);
$location= urlencode($location);
$url = 'https://api.foursquare.com/v2/venues/search?query=' . $location . ' &near=' . $city . '&v=20130815&client_id=xxx&client_secret=xxx';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = json_decode(curl_exec($ch), true);
The response:
[code] => 400
[errorType] => invalid_auth
[errorDetail] => Missing access credentials. See https://developer.foursquare.com/docs/oauth.html for details.
afaik, using the 'userless access' approach does not require oauth. I'm including the client id and secret.
So why am I getting an 'invalid_auth' error ?
if I enter the output of $url in a browser, I get a correct response. If I hard-code the $url, then curl returns a correct response. So why would the dynamic $url generate auth error ?
Solution:
' &near=' should be '&near=' -argh
Related
If anyone is familiar with the Constant Contact V3 API perhaps you can be of help.
We are following the docs here: https://developer.constantcontact.com/api_guide/server_flow.html
I have even copy and pasted the PHP code but am Still receiving a 400 error and can't figure out what to do to fix it.
1st we use this for the auth url
$baseURL = "https://authz.constantcontact.com/oauth2/default/v1/authorize";
$authURL = $baseURL . "?client_id=" . $this->_clientID . "&response_type=code&scope=".urlencode('offline_access')."&state=" . $this->user->info['id'] . "&redirect_uri=" . urlencode(DOMAIN.'connect/constantcontact/');
This works and we do receive a code from constant contact.
Next we use the following code to ask for an access token
// Use cURL to get access token and refresh token
$ch = curl_init();
// Define base URL
$base = 'https://authz.constantcontact.com/oauth2/default/v1/token';
// Create full request URL
$url = $base . '?code=' . $_GET['code'] . '&redirect_uri=' . urlencode(DOMAIN.'connect/constantcontact/') . '&grant_type=authorization_code';
//echo $url;
curl_setopt($ch, CURLOPT_URL, $url);
// Set authorization header
// Make string of "API_KEY:SECRET"
$auth = $this->_clientID . ':' . $this->_clientSecret;
//echo $auth;
// Base64 encode it
$credentials = base64_encode($auth);
// Create and set the Authorization header to use the encoded credentials, and set the Content-Type header
$authorization = 'Authorization: Basic ' . $credentials;
curl_setopt($ch, CURLOPT_HTTPHEADER, array($authorization, 'Accept: application/json', 'Content-Type: application/x-www-form-urlencoded'));
// Set method and to expect response
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Make the call
$result = curl_exec($ch);
curl_close($ch);
The response we receive is just a 400 error every time.
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>
Any help or insight on how to fix this would be greatly appreciated. In a bit of a time pinch.
Solved. The following fields were also needed in the post body.
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['client_id' => $this->_clientID, 'client_secret' => $this->_clientSecret, 'code' => $_GET['code']]) );
I am trying to connect to the Marketo.com REST API using curl.
I can't get a response from the identity service. I only get an error message
"[curl] 6: Couldn't resolve host 'MY_CLIENT_ENDPOINT.mktorest.com'
,
but I can print the constructed url and paste it into a browser address bar and this will provide the expected response with the access_token element.
I can use curl in php and in a terminal to access my gmail account so curl is able to access an https service.
I have tried sending the parameters in the curl url as a get request and also by declaring them with curl's -F option as a post request
My application uses dchesterton/marketo-rest-api available on github, but I have also tried a simple php curl request just to get the access token.
private function getToken() {
$url = "$this->client_url/identity/oauth/token?grant_type=client_credentials&client_id=$this->client_id&client_secret=$this->client_secret";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$errors = curl_error($ch);
curl_close($ch);
file_put_contents($this->logDir . 'access_token_response' . date('Y-m-d') . '.txt', $url . "\n" . $response . "\n", FILE_APPEND);
if ($errors) {
file_put_contents($this->logDir . 'access_token_errors' . date('Y-m-d') . '.txt', $errors . "\n", FILE_APPEND);
}
return $response['access_token'];
}
Again, this fails with the same error but produces a perfectly formed url that I can paste into the browser and get a valid response.
I have also tried this using post instead of get as I have for every other test mentioned, and these have been tried on my localhost and on a test server.
Can anyone explain to me why this would fail?
Does Marketo block curl on a per account basis?
I was trying to implement something similar but my code wasn't working. I'm not sure exactly what is failing but I tried your code and it seems to work perfectly after some slight modifications:
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($request_data));
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$response = curl_exec($curl);
$errors = curl_error($curl);
curl_close($curl);
I hope this helps.
I'm trying to write a small PHP code that should be able to authenticate itself to a Google Account and then upload a file to its Google Drive.
This process should be done in two steps:
send the authentication request and get in exchange the authorization code
POST the authorization code and get in exchange the access token that should be used to send other requests (eq: a file upload) to the Google Drive
Note that by using the Google Client Library everything works smoothly.
What I want to achieve is to NOT use the Google Client Library but instead to use the simple authentication steps described here.
By using these authentication steps mentioned earlier I send a request:
https://accounts.google.com/o/oauth2/auth?scope=email%20profile&redirect_uri=http://example.com&response_type=code&client_id=[my-client-id]
and in exchange the redirected page should contain the "code=xxxx" parameter, like:
http://example.com?code=xxx
where xxx is the authorization code prepended by Google to the redirect_uri mentioned above.
The problem is that the Google returns an error message like Moved Temporarily and also provides a link "The document has moved here.". If I click that link then everything works just fine.
But I don't want the user intervention because this code works at the server level and not at the client level.
How to solve this? Please don't answer with "use the Google Client Library!" because I've already said that by doing so it will work but I don't want the Google Client Library dependency!
My PHP code is:
$CLIENT_ID = '[the client ID from Google Developer Console]';
$CLIENT_SECRET = '[the client secret from Google Developer Console]';
$REDIRECT_URI = 'http' . ($_SERVER['SERVER_PORT'] == 80 ? '' : 's') . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME'];
$ch = curl_init();
if (isset($_GET['code']))
{
$url = 'https://accounts.google.com/o/oauth2/token';
$post_fields = 'code=' . $_GET['code'] . '&client_id=' . $CLIENT_ID . '&client_secret=' . $CLIENT_SECRET . '&redirect_uri='
. $REDIRECT_URI . '&grant_type=authorization_code';
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER,
array('Host:accounts.google.com', 'Content-Type:application/x-www-form-urlencoded', 'Content-Length:' . strlen($post_fields))
);
}
else
{
$url = sprintf('https://accounts.google.com/o/oauth2/auth?scope=email%%20profile&redirect_uri=%s&response_type=code&client_id=%s',
$REDIRECT_URI, $CLIENT_ID
);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$error_no = curl_errno($ch);
curl_close($ch);
echo $result;
?>
The solution for this kind of problem is:
don't call the first request via CURL but by changing the document Location
Also change this block:
...
else
{
$url = sprintf('https://accounts.google.com/o/oauth2/auth?scope=email%%20profile&redirect_uri=%s&response_type=code&client_id=%s',$REDIRECT_URI, $CLIENT_ID);
}
with this one:
...
else
{
$url = sprintf('https://accounts.google.com/o/oauth2/auth?scope=email%%20profile&redirect_uri=%s&response_type=code&client_id=%s',$REDIRECT_URI, $CLIENT_ID);
header('Location:'.$url);
}
I need to get the twitter latest feed of the user. i used
https://api.twitter.com/1/statuses/user_timeline.json?oauth_token=ecwmW3pMB8euREHVljdySRexys6c6XYangqEANY&screen_name=twitter_name&count=1
but i get "Rate limit exceeded" cliente could not make 150 request per hour.
I used twitter Oauth request using consumer key, consumer secret , access token and access secret and the code as follows
$oauth_consumer_key="Vqlj7vd9yHo5MZPnWGf3w";
$oauth_nonce="af00a3a26b15ec0178ce0342acc9b392";
$oauth_signature_method="HMAC-SHA1";
$oauth_timestamp="1341408794";
$oauth_token="620811780-30jD4XHWFvp15RcjmxHkLLicFlvMDuNaWp6fKjia";
$oauth_version="1.0";
$oauth_signature=rawurldecode("N6L4VJLJjY%2BPKxoelttqe2GOPAw%3D");
$url = "https://api.twitter.com/1/statuses/user_timeline.json?";
$url .= "screen_name=twitter_name";
$url .= "&oauth_consumer_key=".$oauth_consumer_key."";
$url .= "&oauth_token=".$oauth_token."";
$url .= "&oauth_nonce=".$oauth_nonce."";
$url .= "&oauth_signature_method=".$oauth_signature_method."";
$url .= "&oauth_timestamp=".$oauth_timestamp."";
$url .= "&oauth_version=1.0";
$url .= "&oauth_signature=".$oauth_signature."";
$url .= "&count=1";
$url .= "&include_rts=true";
$url .= "include_entities=true";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Host: api.twitter.com'));
$json = curl_exec($ch);
curl_close ($ch);
$data = json_decode($json, true);
print_r($json);
still i get the rate limit exceeded error.
could any one help me get twitter latest feed using Oauth.
Thanks.
From experience Twitter OAuth is hit and miss if you try to handle negotiations yourself. I tried for several weeks to achieve this but kept having errors like 'Rate limit exceeded' and 'Invalid OAuth Key'. I checked out a library and within the same hour I could get statuses, set statuses, send tweets with and without pics etc..
Here's what I'm using now, test it out. It's lightweight and easy to use.
https://github.com/themattharris/tmhOAuth/
I found this function that supposedly gets the accessToken, but I get nothing.
I do have the $_REQUEST['code'], and the other information needed in this function.
Any ideas what is wrong here?
Thanks.
//Oauth 2.0: exchange token for session token so multiple calls can be made to api
if(isset($_REQUEST['code'])){
$_SESSION['accessToken'] = get_oauth2_token($_REQUEST['code']);
}
//returns session token for calls to API using oauth 2.0
function get_oauth2_token($code) {
global $client_id;
global $client_secret;
global $redirect_uri;
$oauth2token_url = "https://accounts.google.com/o/oauth2/token";
$clienttoken_post = array(
"code" => $code,
"client_id" => $client_id,
"client_secret" => $client_secret,
"redirect_uri" => $redirect_uri,
"grant_type" => "authorization_code"
);
$curl = curl_init($oauth2token_url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $clienttoken_post);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$json_response = curl_exec($curl);
curl_close($curl);
$authObj = json_decode($json_response);
if (isset($authObj->refresh_token)){
//refresh token only granted on first authorization for offline access
//save to db for future use (db saving not included in example)
global $refreshToken;
$refreshToken = $authObj->refresh_token;
}
$accessToken = $authObj->access_token;
return $accessToken;
}
This is what I did to get my access token and refresh token.
Create a file that contains the following code :
<?php
if (isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://accounts.google.com/o/oauth2/token';
$params = array(
"code" => $code,
"client_id" => YOUR_CLIENT_ID,
"client_secret" => YOUR_CLIENT_SECRET,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"grant_type" => "authorization_code"
);
$ch = curl_init();
curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($info['http_code'] === 200) {
header('Content-Type: ' . $info['content_type']);
return $output;
} else {
return 'An error happened';
}
} else {
$url = "https://accounts.google.com/o/oauth2/auth";
$params = array(
"response_type" => "code",
"client_id" => YOUR_CLIENT_ID,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"scope" => "https://www.googleapis.com/auth/plus.me"
);
$request_to = $url . '?' . http_build_query($params);
header("Location: " . $request_to);
}
Now, replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with your client ID and client secret.
Make sure your scope is correct. For example, it should be https://www.googleapis.com/auth/analytics if you want to get access to Analytics.
If you run the file, you should get an OAuth2 approval screen.
If you now press Accept, you should get a result that looks like this:
{
"access_token" : YOUR_ACCESS_TOKEN,
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : YOUR_REFRESH_TOKEN
}
The result may contain additional fields, depending on which scope you're applying for.
I don't see anything wrong with your code, but you may want to try refreshing the client secret and see if that helps. Additionally, I would suggest you see exactly what the response is coming back from your curl command, I suspect it's "invalid_grant".
A much better way to do this is to use google's php api client:
https://code.google.com/p/google-api-php-client/
which handles most of the communication for you. The examples there are very easy to use. It mostly depends on which google service you are trying to access.
that code looks familiar - I'm using roughly the same code - there are two things you can try.
Use echo to echo the response to the Browser
echo $json_response;
Get hold of Fiddler and use the following line before the call to curl_exec
curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:8888');
'fraid I've not got it working either - the response I am getting is
{
"error" : "invalid_request"
}
Now if anyone knows how what is wrong with this ;)
From section 4.4.2 of "The OAuth 2.0 Authorization Protocol draft-ietf-oauth-v2-20"
The client makes a request to the token endpoint by adding the
following parameters using the "application/x-www-form-urlencoded"
format in the HTTP request entity-body:
So the POSTed parameters should be submitted in the form of a string, not an array. This is mentioned in the PHP manual for curl_setopt too.
So instead of posting $clienttoken_post, you might want to post http_build_query($clienttoken_post,'','&').
This might not solve all your problems, but it's probably a step in the right direction.
I had the same error, and I found that adding
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
to allow the request follow a redirect solved it quickly. I hope that helps someone else!