OAuth2.0 request access_token using cURL security - oauth

I am an newbie on using the OAuth2.0. Right now, I am requesting an access_token using cURL and it works very well as expected. But my concern now is, is this secured? because, the client_id and client_secret can be exposed? or there will be a secured way to connect/request an access_token to the OAuth server? Thank you so much.
$post = [
'grant_type' => 'client_credentials',
];
$ch = curl_init('http://laravelxampp.dev/oauth/access_token');
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Basic ZjNkMjU5ZGRkM2VkOGZmMzg0MzgzOWI6NGM3ZjZmOGZhOTNkNTljNDU1MDJjMGFlOGM0YTk1Yg==',
'Accept: application/json',
'Accept-Language: en_US'
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
$secret = json_decode($response);
return $secret->access_token;

The request is supposed to happen over a TLS protected connection (i.e. using a https URL) instead of over plain HTTP; by doing it over TLS the confidentiality of the client secret is guaranteed.
As RFC 6749 says in https://www.rfc-editor.org/rfc/rfc6749#section-3.2:
Since requests to the token endpoint result in the transmission of
clear-text credentials (in the HTTP request and response), the
authorization server MUST require the use of TLS as described in
Section 1.6 when sending requests to the token endpoint.
So your example shows a non-compliant Authorization Server accepting a non-protected request.

Related

QuickBooks Oauth 2.0 returning Invalid Request Error while getting accesstoken

I am trying to Authorize the quick-books using Oath 2.0. I have done with authorization and now trying to get access token. But while making POST request to get access token I am getting "Invalid Request Error".
`$adminUrl="https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
$client_id='Q0ble08jhv8hvQwLbBo******************';
$client_secret='ewHQsRokdOhOjcNHpt7wH***********';
$redirect_url='http://localhost/quickbooks/testaccesstoken.php';
//According to Quickbooks API need to pass Authorization Header//
$authorizationToken=base64_encode($client_id."".$client_secret);
//Curl Post Request//
$ch = curl_init();
$data = array("code" =>$code,"redirect_uri"=>$redirect_url,"grant_type"=>"authorization_code");
$headers = array();
$ch = curl_init($adminUrl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT__TIMEOUT, "30");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization:Basic' .$authorizationToken,'Content-Type: application/x-www-form-urlencoded','Accept: application/json'));
$token = curl_exec($ch);
{"error":"invalid_request"}

How to send request to google server in php using a stored refresh_token or a password?

My goal is to manage to use the Google APIs in general, in particular here i need to send emails using Gmail API.
I saved in the DB the 'refresh_token' given to me from Google Server the first time i did the login (using Gmail credentials), and now, as written into the guides, it seems that I have to do a server request (I'm using PHP) to the google server like the following.
[I looked also here:
https://developer.salesforce.com/forums/?id=906F00000008tKWIAY
https://developers.google.com/identity/protocols/OAuth2InstalledApp#formingtheurl
]
My code is the following:
$data = //'grant_type=refresh_token'.
//'&refresh_token='.$refreshtoken; (first option)
'&grant_type=password'.
'&username=mygmail'.
'&password=mypasswordgmail'; (second option)
'&client_id='."xxx".
'&client_secret='."yyy".
$additional_headers = array('Content-Type: application/x-www-form-urlencoded');
$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $additional_headers);
$server_output = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $status != 200 )
{
echo 'token_url: '.$token_url."<br>";
echo 'params: '.$data."<br><br>";
echo 'response: '.$server_output."<br>";
die("Error: call to URL $token_url failed with status $status<br>");
}
curl_close($ch);
And what I get as an answer is something like (using password):
response: { "error": "unsupported_grant_type", "error_description": "Invalid grant_type: password" }
Error: call to URL https://www.googleapis.com/oauth2/v4/token failed with status 400
Or (using the refresh_token):
response: { "error": "invalid_grant", "error_description": "Bad Request" }
Error: call to URL https://www.googleapis.com/oauth2/v4/token failed with status 400
I use this in the rest of the code:
$guzzleClient = new \GuzzleHttp\Client(array('curl' => array(CURLOPT_SSL_VERIFYPEER => false, ), ));
$redirectUri = "http://".$_SERVER["HTTP_HOST"].$_SERVER['PHP_SELF'];
$gclient = new Google_Client();
$gclient->setHttpClient($guzzleClient);
$gclient->setAuthConfig('client_secret/client_secret.json');
$gclient->setRedirectUri($redirectUri);
$gclient->setAccessType('offline');
$gclient->setApprovalPrompt('force');
$gclient->addScope("https://mail.google.com/");
$gclient->addScope("https://www.googleapis.com/auth/gmail.compose");
$gclient->addScope("https://www.googleapis.com/auth/gmail.modify");
$gclient->addScope("https://www.googleapis.com/auth/gmail.readonly");
$gclient->addScope('https://www.googleapis.com/auth/userinfo.email');
$gclient->addScope('https://www.googleapis.com/auth/userinfo.profile');
what's wrong??
According to this documentation, requests to the Gmail API must be authorized using OAuth 2.0 credentials. You should use server-side flow when your application needs to access Google APIs on behalf of the user, for example when the user is offline. This approach requires passing a one-time authorization code from your client to your server; this code is used to acquire an access token and refresh tokens for your server.
You may refer with this thread regarding your "Invalid grant_type: password" error. It suggested to specify access_type=offline in your request.
Here's an additional reference which might also help.

Google email settings api error 403 with php curl

I am trying to update a signature through the Google email settings api. The domain is an EDU account, the user in question is a super admin. After successfully retrieving an OAuth 2.0 token, i issue this php curl code:
$mydomain = '<mydomain.com>';
$myuser = '<myusername>';
$token = '<mytoken>';
$url = 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/'.$mydomain.'/'.$myuser.'/signature'
$data = '<?xml version="1.0" encoding="utf-8"?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:apps="http://schemas.google.com/apps/2006">
<apps:property name="signature" value="blabla" />
</atom:entry>';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml', 'Authorization: Bearer '.$token));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
curl_close ($ch);
Which results in:
You are not authorized to access this API. Error 403
Because of other issues mentioned here about the client_id when getting authorized, i have tried the above with both the gserviceaccount.com address and the googleusercontent.com address, with the same results.
What am i doing wrong here?
To answer my own question: after speaking to a Google rep i have learned that the email settings api cannot be used through standard "web app" authorization but needs to be used through a "service account":
https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Unable to refresh Reddit OAuth 2.0 access token

I cannot refresh the Reddit access token.
When I send following request to https://ssl.reddit.com/api/v1/access_token
Content-Type: application/x-www-form-urlencoded
Authorization: #####
client_secret=#####&grant_type=refresh_token&client_id=#####&refresh_token=#####
I get status 200 but content is {"error": "invalid_request"}.
According to OAuth 2.0 spec and Reddit spec I do everything right.
I've also tried it without client_id and client_secret with the same result.
Am I missing something?
Reddit's OAuth implementation is really unique (and not in a good way).
The necessary parameters for refreshing tokens on reddit are:
client_id
client_secret
grant_type (=refresh_token)
refresh_token
scope
state
duration
redirect_uri
You'll also need the basic HTTP authentication header with client_id as login and client_secret as password.
I had to look up reddit's source code to figure out what was missing from my requests... So much development time lost on trivial matters.
In case anyone is looking for more explicit answer:
Here is how I did this in PHP.
$authorizeUrl = 'https://ssl.reddit.com/api/v1/access_token';
$clientId = "YOUR_CLIENT_ID";
$clientSecret = "YOUR_CLIENT_SECRET";
$post = array(
"client_id" => $clientId,
"client_secret" => $clientSecret,
"grant_type" => "refresh_token",
"refresh_token" => "STORED_REFRESH_TOKEN_VALUE",
"scope" => "identity",
"state" => "WHATEVER_VALUE",
"duration" => "temporary",
"redirect_uri" => "https://example.com/reddit",
);
$payload = http_build_query($post);
$ch = curl_init($authorizeUrl);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_USERPWD, $clientId . ":" . $clientSecret);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
print_r($result);

Accessing Clickbank API through Delphi's TIdHTTP?

I am trying to access the ClickBank API from my Delphi project, to check if a customer has a valid subscription.
I found the API Documentation here, but there are no Delphi examples. So I am trying to create my own little example, however I just cant figure it out with Indy's TIdHTTP.
Could anyone point me in the right direction, perhaps set up a minimal example?
P.S: I tried looking at the C# sample, however I cant port it to Delphi.
ClickBank sample C# is found here https://sandbox.clickbank.com/api_12_examples/api_example.csharp
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create("https://api.clickbank.com/rest/1.2/orders/list");
request.Accept = "application/xml";
request.Headers.Add(HttpRequestHeader.Authorization,
"<< DEVELOPER KEY >>:<< API KEY >>");
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
The PHP version is
https://sandbox.clickbank.com/api_12_examples/api_example.php
You'll see that they aren't doing much setup here... just setting two headers and performing a GET.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.clickbank.com/rest/1.2/orders/list");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_GET, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Accept: application/xml",
"Authorization: << DEVELOPER KEY >>:<< API KEY >>"));
$result = curl_exec($ch);
curl_close($ch);
In Delphi - a quick demo is to drop a TIdHTTP1 client on a form, along with a Button and a Memo. Then on an onclick of the button (where xxx= your developer key and yyy= your api key) do the same - set two headers and perform a GET:
IdHTTP1.Request.Accept := 'application/xml';
IdHTTP1.Request.CustomHeaders.Add('Authorization: xxx:yyy');
Memo1.Text := IdHTTP1.Get('https://api.clickbank.com/rest/1.2/orders/list');

Resources