I am using file_get_contents in PHP to make HTTP requests to the Twitter API.
When trying to request a token, I get the error:
Warning: file_get_contents(https://api.twitter.com/oauth/request_token): failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized
Here is my code
$appID = "MY-CONSUMER-ID";
$appSecret = "MY-CONSUMER-SECRET";
$url = "https://api.twitter.com/oauth/request_token";
$oauth = array(
"oauth_nonce" => base64_encode(time()),
"oauth_callback" => "MY-URL",
"oauth_signature_method" => "HMAC-SHA1",
"oauth_timestamp" => time(),
"oauth_consumer_key" => $appID,
"oauth_version" => "1.0"
);
$token_string = "POST&" . rawurlencode($url) . "&" . rawurlencode(http_build_query($oauth));
$signing_key = rawurlencode($appSecret) . "&";
$signature = base64_encode(hash_hmac("sha1", $token_string, $signing_key, true));
$oauth["oauth_signature"] = $signature;
$header = array();
foreach ($oauth as $key => $value) { $header[] = rawurlencode($key) . "=\"" . rawurlencode($value) . "\""; }
$header = implode(", ", $header);
$header = "Authorization: OAuth " . $header;
echo $header;
$opts = array('http' => array(
'method' => "POST",
'header' => $header,
) );
$context = stream_context_create($opts);
$result = file_get_contents($url, false, $context);
You actually helped me and I'll help anyone else who reads this post.
The issue why this wasn't working was because the $oauth array must be in alphabetical order (see https://dev.twitter.com/docs/auth/creating-signature). Thus when it is http_build_queried it was wrong.
However this helped me because my signature was passing an expected o_token when we don't at this point have one (I use this code for signing all requests) so $signing_key = rawurlencode($appSecret) . "&"; helped fix my problem.
Related
I am getting the error Warning: file_get_contents(https://partner.uat.shopeemobile.com/api/v1/item/categories/get): failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request in C:\xampp\htdocs\addproduct.php on line 43
<?php
$api_authorization_base_url = "https://partner.shopeemobile.com/api/v1/shop/auth_partner";
$redirect_url = "https://www.google.com";
$partner_id = 840565;
$shopid = 209194;
$key = "aca9b2236136e7aeb8be2b11197a181cd6bc672cbc641f8fe41d0850b7b7f63a";
$token_base_string = $key . $redirect_url;
$token = hash('sha256', $token_base_string);
$data = array(
'id' => $partner_id,
'token' => $token,
'redirect' => $redirect_url
);
$api_authorization_url = $api_authorization_base_url . "?" . json_encode($data);
// echo $api_authorization_url . "\n";
$get_order_by_status_url = "https://partner.uat.shopeemobile.com/api/v1/item/categories/get";
$data = array(
'partner_id' => $partner_id,
'shopid' => $shopid,
'timestamp' => time(),
"language" => "en"
);
$sig_base_string = $get_order_by_status_url . " |" . json_encode($data);
$sig = hash_hmac('sha256', $sig_base_string, $key);
$header = [
'Authorization' => $sig
];
$options = array(
'http' => array(
'header' => "Content-type: application/json\r\n Authorization: " . $sig,
'method' => 'POST /api/v1/item/categories/get HTTP/1.1',
'content' => json_encode($data)
),
);
$context = stream_context_create($options);
// print_r($sig_base_string);
$result = file_get_contents($get_order_by_status_url, false, $context);
print_r($result);
?>
In the $options array you have 'method' and you are passing in invalid stuff, method should be just a valid HTTP request method like POST or GET etc.
I'm trying to follow the Using OAuth 2.0 for Server to Server Applications guide to get an access token so that I can use the Youtube Reporting API.
But no matter what I do, I always this result:
Warning: file_get_contents(https://www.googleapis.com/oauth2/v4/token): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
Here's my code
$contents = file_get_contents('BCGA-557d334b8526.json');
$account = json_decode($contents, TRUE);
$privateKeyString = $account['private_key'];
$time = time();
$expiration = $time + 3600;
$header = '{"alg":"RS256","typ":"JWT"}';
$claim_set = '{"iss":"youtube-reporting#ataproject-850089.iam.gserviceaccount.com","scope":"https://www.googleapis.com/auth/yt-analytics.readonly","aud":"https://www.googleapis.com/oauth2/v4/token","exp":"' . $expiration . '","iat":"' . $time . '"}';
$unsignedToken = base64_encode($header) . '.' . base64_encode($claim_set);
$signature = hash_hmac('sha256', $unsignedToken, $privateKeyString, true);
$jwt = base64_encode($header) . '.' . base64_encode($claim_set) . '.' . base64_encode($signature);
$url = "https://www.googleapis.com/oauth2/v4/token";
$data = array('grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt);
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
var_dump($result);
Any suggestions?
You forgot
'grant_type' => 'refresh_token'
I am trying to use file_get_contents to "post" to a url and get auth token. The problem I am having is that it returns a error.
Message: file_get_contents(something): failed to open stream: HTTP request failed! HTTP/1.1 411 Length Required.
I am not sure what is causing this but need help. Here is the function.
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$context = stream_context_create(array (
'http' => array (
'header' => 'Authorization: Basic ' . base64_encode("$username:$password"),
'method' => 'POST'
)
));
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
I tried it with POSTMAN, and it works, so only problem I am having is that why isnt it working with file_get_contents.
Cannot command so i will do it this way. If you use Postman why don't you let Postman generate the code for you. In postman you can click code at a request and you can even select in what coding language you wanne have it. Like PHP with cURL:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://somthing.com/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => array(
"password: somthing",
"username: gettoken"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Hope this will help!
I can not comment because of my reputation;
In some servers file_get_content is not available...
You may try with CURL like this
Your request havent any data and content length is missing.
You can try this:
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$data = array('foo' => 'some data');
$data = http_build_query($data);
$context_options = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
. "Authorization: Basic " . base64_encode("$username:$password") . "\r\n"
. "Content-Length: " . strlen($data) . "\r\n",
'content' => $data
)
);
$context = context_create_stream($context_options);
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
Here is similar problem:
How to fix 411 Length Required error with file_get_contents and the expedia XML API?
RFC2616 10.4.12
https://www.rfc-editor.org/rfc/rfc2616#section-10.4.12
Code: (Doesn't work, see below)
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$context = stream_context_create(array (
'http' => array (
'header' => 'Authorization: Basic ' . base64_encode("$username:$password") . 'Content-Length: ' . strlen($url) . '\r\n',
'method' => 'POST'
)
));
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
2nd Try:
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$context_options = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n" . "Authorization: Basic " . base64_encode("$username:$password") . "Content-Length: " . strlen($url) . "\r\n",
'content' => $url
)
);
$context = stream_context_create($context_options);
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
This is from patryk-uszynski's answer formatted with the OP's code.
since a week I'm trying to manage "Login with twitter" functionality in my website. I can not complete even the first step: 'obtain a request token'. I recieve:
"Failed to validate oauth signature and token"
I'm doing everything like said here: https://dev.twitter.com/docs/auth/implementing-sign-twitter
And creating a signature like here: https://dev.twitter.com/docs/auth/creating-signature
My code:
date_default_timezone_set('UTC');
$oauth_callback = 'http://mydomain.net'; // calls are made from index.php
$url = 'https://api.twitter.com/oauth/request_token';
$oauth_consumer_key = '***';
$oauth_nonce = str_shuffle(trim(base64_encode(time()), '='));
$oauth_signature_method = 'HMAC-SHA1';
$oauth_timestamp = time();
$oauth_token = '***';
$oauth_version = '1.0';
$HTTPMethod = 'POST';
$BaseURL = 'https://api.twitter.com/oauth/request_token';
$consumer_secret = '***';
$access_token_secret = '***';
$params = array(
'oauth_consumer_key' => $oauth_consumer_key,
'oauth_nonce' => $oauth_nonce,
'oauth_signature_method' => $oauth_signature_method,
'oauth_timestamp' => $oauth_timestamp,
'oauth_token' => $oauth_token,
'oauth_version' => $oauth_version,
'oauth_callback' => $oauth_callback
);
function parameter_string (array $params)
{
$temp_array = array();
$parameter_string = '';
while (current($params)) {
$temp_array[rawurlencode(key($params))] = rawurlencode(current($params));
next($params);
}
ksort($temp_array);
foreach ($temp_array as $key => $value) {
$parameter_string .= '&' . $key . '=' . $value;
}
return trim($parameter_string, '&');
}
$parameter_string = parameter_string($params);
function signature_base_string ( $HTTPMethod, $BaseURL, $parameter_string)
{
$signature_base_string = $HTTPMethod . '&' . rawurlencode($BaseURL) . '&' . rawurlencode($parameter_string);
return $signature_base_string;
}
$signature_base_string = signature_base_string ($HTTPMethod, $BaseURL, $parameter_string);
function signing_key($consumer_secret)
{
return rawurlencode($consumer_secret) . '&';
}
$signing_key = signing_key($consumer_secret);
$oauth_signature = base64_encode(hash_hmac('SHA1', $signature_base_string, $signing_key, true));
$header[] = 'Authorization: OAuth '.
'oauth_callback="'.rawurlencode($oauth_callback).'", '.
'oauth_consumer_key="'.rawurlencode($oauth_consumer_key).'", '.
'oauth_nonce="'.rawurlencode($oauth_nonce).'", '.
'oauth_signature="'.rawurlencode($oauth_signature).'", '.
'oauth_signature_method="'.rawurlencode('HMAC-SHA1').'", '.
'oauth_timestamp="'.rawurlencode($oauth_timestamp).'", '.
'oauth_version="'.rawurlencode('1.0').'"';
$options = array(
CURLOPT_URL => $url,
CURLOPT_HEADER => true,
CURLINFO_HEADER_OUT => true,
CURLOPT_HTTPHEADER => $header,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true
);
$c = curl_init();
$d = curl_setopt_array($c, $options);
$response = curl_exec($c);
echo '<pre>';
print_r($response);
echo '</pre>';
echo '<pre>';
print_r (curl_getinfo($c));
echo '</pre>';
curl_close($c);
The request header looks like this:
POST /oauth/request_token HTTP/1.1
Host: api.twitter.com
Accept: */*
Authorization: OAuth oauth_callback="http%3A%2F%2Fmydomain.net", oauth_consumer_key="***", oauth_nonce="2DHXEIM541CPONJS3UFRQ79G8W0KA6LYZBT", oauth_signature="***", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1379239417", oauth_version="1.0"
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
Please help!
If cURL is unavailable I want to send HTTP requests using fopen. I got the code for a class from a PACKT RESTful PHP book but it does nto work. Any ideas why?
if ($this->with_curl) {
//blah
} else {
$opts = array (
'http' => array (
'method' => "GET",
'header' => array($auth,
"User-Agent: " . RESTClient :: USER_AGENT . "\r\n"),
)
);
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = fpassthru($fp);
fclose($fp);
}
return $result;
}
The HTTP context options are laid out here: http://www.php.net/manual/en/context.http.php
The header option is a string, so as #Mob says you should be using \r\n and string concatenation rather than an array. However, user_agent is a valid key, so you could just use that instead.
I'm guessing that the contents of the $auth variable is something along the lines of Authorization: blah - i.e. standard header format?
The below code is a working example. Note that I've changed your fpassthru() (which outputs the content to the browser, and does not store it to $result) to a fread() loop. Alternatively you could have wrapped the fpassthru() call with ob_start(); and $result = ob_get_clean();
<?php
class RESTClient {
const USER_AGENT = 'bob';
}
$url = 'http://www.example.com/';
$username = "fish";
$password = "paste";
$b64 = base64_encode("$username:$password");
$auth = "Authorization: Basic $b64";
$opts = array (
'http' => array (
'method' => "GET",
'header' => $auth,
'user_agent' => RESTClient :: USER_AGENT,
)
);
$context = stream_context_create($opts);
$fp = fopen($url, 'r', false, $context);
$result = "";
while ($str = fread($fp,1024)) {
$result .= $str;
}
fclose($fp);
echo $result;
You're mixing this. Shouldn't it be ::
$opts = array (
'http' => array (
'method' => "GET",
'header' => $auth . "\r\n" . //removed array()
"User-Agent: " . RESTClient :: USER_AGENT . "\r\n" )
)
Here's an example of setting headers from the PHP manual
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);