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'
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 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.
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.
One site requires login for three variables: username, password and token. This data is sent via POST.
token is also sent through a section.
I have all three variables, and I want to log in via file_get_contents.
How can that data be sent and the authentication is successful?
function file_post_contents()
{
$url = 'http://site.com/auth.php?' . session_name() . '=' . session_id();
$login = 'jhon';
$senha = 'doe';
$token = '123456';
$_SESSION["token"] = $token;
$postdata = http_build_query(
array(
'login' => $login,
'senha' => $senha,
'token' => $token,
$_SESSION["token"] => $token
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
if($login && $senha)
{
$opts['http']['header'] = ("Authorization: Basic " . base64_encode("$login:$senha"));
}
$context = stream_context_create($opts);
return file_get_contents($url, false, $context);
}
Modified code. It does not work.
function file_post_contents()
{
$url = 'http://site.com/auth.php?' . session_name() . '=' . session_id();
$login = 'jhon';
$senha = 'doe';
$token = '123456';
$_SESSION["token"] = $token;
$postdata = http_build_query(
array(
'login' => $login,
'senha' => $senha,
'token' => $token
//, $_SESSION["token"] => $token
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded'
. "\r\n" . "Authorization: Basic " . base64_encode("$login:$senha"). "\r\n",
'content' => $postdata
)
);
$context = stream_context_create($opts);
return file_get_contents($url, false, $context);
}
Your headers might be set wrong, try adding \r\n like so
$opts = array('http' =>
array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'content' => $postdata
)
);
and later down the code
$opts['http']['header'] = $opts['http']['header'] . "Authorization: Basic " . base64_encode("$login:$senha") . "\r\n";
You're overriding $opts['http']['header'] with the Basic auth. You're not adding it to the Content-type, you're replacing Content-type with it.
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"
)
);