How to authorize post request in REST API? - php

I'm sitting here working on making a post request in a rest api in php using curl. For this purpose I have the api key and an auth key, which I am currently including as post values in the request. But I keep getting HTML back in my response instead of JSON data (which its supposed to be) giving me a 401 unauthorized error.
I've noticed often you need to make custom headers to authorize yourself in these cases (I'm guessing I need to use my auth key for that, in the header somehow).
This is my code:
$post = [
'apikey' => $apiKey,
'authkey' => $authKey,
'name' => $reknr,
'description' => $opgave,
'clientId' => $clientId,
'orderTypeId' => $typeId,
'contactAddressId' => $addressId,
'theirref' => $ref,
'reqno' => $reknr
];
// Set api link
$ch = curl_init('https://app.minuba.dk/api/1/Order');
// Set return value to true
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Configure header
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: Basic '.$authKey,
'Content-Type: application/json')
);
// Add post fields
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
The API docs doesn't say anything about how you authorize yourself when making post request, during get requests its fairly easy you just include the apikey and authkey as normal parameters and it works fine.
My question is, how do I know how to configure my header so the API authorizes me? The docs say nothing about it or offers any explanation as to how except mentioning you need both the apikey and authkey to gain access.
I admit my understand of the http headers are limited, but how do I know how to configure it for this particular api?
UPDATE:
Found out the header response gives me this line:
WWW-Authenticate: Basic realm="Minuba REST API"
This tells me that the method I'm using to authenticate should be correct right? So why am I still getting a 401?

Related

How to send a POST request to sellix in php

I'm trying to use sellix.io API to create a payment in PHP, everything works fine in local until I upload the code to the webhost, there I get
{"status":400,"data":null,"message":null,"log":null,"error":"Transaction flagged as potential fraud (xxxxxxxxxxx).","env":"production"}
It says my request is flagged as a potential fraud. Asking around I got told that "sending a payment request from a server which can be considered a VPN or a RDP with no useragent nor fingerprint of that device may be flagged"
How can I send the request with a proper useragent? or fingerprint?
this is the code I've been using:
<?php
$mail = $_GET["mail"];
$url = "https://dev.sellix.io/v1/payments";
$data = json_encode(array(
"title" => "MyProduct",
"product_id" => "xxxxxxxxxxx",
"gateway" => "PAYPAL",
"value" => 20,
"currency" => "EUR",
"quantity" => 1,
"email" => $mail,
"white_label" => false,
"return_url" => "https://dev.sellix.io/v1/return" //not sure what this is supposed to do...
));
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
// "Content-type: application/x-www-form-urlencoded\r\n" .
'Authorization: Bearer ' . 'xxxxxxxxxxxxxxxx(API KEY)xxxxxxxxxxxxxxxx'
));
echo $response = curl_exec($curl);
curl_close($curl);
$finalUrl = strval(json_decode($response)->data->url);
header("Location: $finalUrl"); //redirects the current page to the payment page.
?>
This is a guess based on the lack of information related to your question on their help page and API documentation. I have listed some tips in the order I would try to debug this:
1: Sending user agent header
Try adding the user-agent header of your client. this will be available in $_SERVER['HTTP_USER_AGENT']
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"User-agent: ".$_SERVER['HTTP_USER_AGENT']."\r\n" .
'Authorization: Bearer ' . 'xxxxxxxxxxxxxxxx(API KEY)xxxxxxxxxxxxxxxx'
));`
Caveat: If you are doing some custom ajax you may not get the header. You can also provide a static value, but essentially avoiding fraud is in your best interest.
2: Adding a fingerprint header/cookie
Fingerprinting is (apparently) sending information to identify the browser. according to this OWASP article it could be stored in a cookie called __Secure-Fgp which you would have to add to the request.
This SO answer goes some way to show one method of calculating the firngerprint client side.
Disclaimer: I have not tried this myself. and I would query their support if there is a header this would fit into.
3: Debugging with another product
According to their help page you can set the "max_risk_level" to 100 on a POST /products call, in order to turn off their fraud engine DO NOT DO THIS IN PRODUCTION fraud prevention mechanics are there to prevent you from being cheated as well. But it may help you to find out what is going wrong and getting a proof of concept up and running.

Redirecting to a remote URL with POST Method, POST Fields and Header Info in PHP

I've just ran into a situation where i want to POST some data to a remote URL. Apart from POSTing the data, with some header information, i also want the user to be redirected to that POST url.
Let me explain the scenario here, I'm integrating a third-party Payment Gateway in my web app. I'm Using Laravel. After a chain of API calls, the app is submitting payment details to the API. The API result does have a third-party url (of the respective bank) to which, i need to take the user to complete the authentication process. I have a couple of data and a header info to take along with it. I have tried Laravel Guzzle, but like cURL when we submit the POST data, we'll actually get the response back in our side. But not getting redirected.
If i have to go with a standard html form, how can i post the header information there. Using jQuery ajax could possibly pose the same issue too, that i can't redirect the user.
I have done some re-search and tried something,
With guzzle, i'm actually able to show the HTML content back to the user using the getBody method, but the HTML is not getting parsed the right way, the images are broken (because of the relative path they using in there web pages) and the links and buttons are not taking me to the desired locations.
$response = $client->request('POST', $transactionResponse['redirectForm']['actionUrl'], [
'headers' => $transactionResponse['redirectForm']['headers'],
'form_params' => $transactionResponse['redirectForm']['content']
]);
echo $response->getBody();
I have tried cURL as well with the CURLOPT_FOLLOWLOCATION directive, but it too returns the response, not redirecting the user.
$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender' => 1,
];
$ch = curl_init('http://localhost/laravel/arax_v1/paytm/callback');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'location: http://localhost/laravel/arax_v1/paytm/callback'
));
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
Could anyone have any better idea to work this out ?

LinkedIn oAuth 2 issue with client_id parameter

I'm trying to create an application on LinkedIn that's using OAuth2 for authentication and am running into some errors. The client runs on an iOS device and uses an oAuth library to make a call to LinkedIn's servers. My iOS client successfully gets the authorization_code. The client application then passes that authorization_code to my server, which attempts to connect to linkedIN again and get the access_token. This step consistently fails, I get the following error from LinkedIn: {"error":"invalid_request","error_description":"missing required parameters, includes an invalid parameter value, parameter more than once. : client_id"}
My POST method to LInkedIN does contain the client_id, it only contains it once, and I've triple checked the values for all the parameters, they are correct. I've also reset the access multiple times from https://www.linkedin.com/secure/settings and I've even created additional applications on LinkedIn, I keep getting the same result.
I've checked other responses, such as this one: unable to retrieve access token linkedin api and tried the suggestions: revoke keys, request new keys etc, nothing seems to be working.
Here is my server code:
$tokenURL = 'https://www.linkedin.com/uas/oauth2/accessToken';
$redirectURL = 'https://staging.textsuggestions.com';
$clientId = '75a4ezqh741sup';
$clientSecret = 'XXXXXXXX';
$tokenArguments = array("grant_type" => "authorization_code",
"code" => $code,
"redirect_uri" => $redirectURL,
"client_secret" => $clientSecret,
"client_id" => $clientId);
// send the request to the server getting data
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $tokenURL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $tokenArguments);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!empty($response["error"])) {
error_log("Error is: " . $response["error"]);
exit (0);
} else {
// no error, get the access_token and do stuff with it
$timeout = $response["expires_in"];
$access_token = $response["access_token"];
}
Ok I realized what I was doing wrong, the client application library that I was using was generating the full access token (not the auth code). So I was trying to pass in the access token in the place of the auth code. The error that I was getting from Linked In was certainly misleading and I should have checked the client library I was using more carefully.
Have you tried to check your code against this code sample?
https://developer.linkedin.com/documents/code-samples
Check that the POST headers include "Content-Type": "application/x-www-form-urlencoded".

Twitter bearer access token request behaves differently on two servers

I have to implement the oAuth2 bearer access token method for a twitter feed. I followed correctly the details on the twitter developper website but i keep getting "Unable to verify your credentials twitter"...
If i copy my credentials over to my dev server (5.3.10 machine) i can actually login, get the token, retrieve the tweets, but on another client's server (5.2.17 machine) i can't get it to work with the exact same code.
Anything strikes you in the code below about the PHP differences? I believe it must have to be something to do with the file_get_content https stream wrapper options, but i can't find anything in the doc about it. (Openssl support is installed on the client server)
$twitter_bearer_access_token = get_option('twitter_bearer_access_token', null);
if($twitter_bearer_access_token == null)
{
//Request a bearer access token
$encodedAccessToken = base64_encode(TWITTER_CONSUMER_KEY.':'.TWITTER_CONSUMER_SECRET);
//Setup the stream context options and create the stream to POST to twitter
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Authorization: Basic '.$encodedAccessToken,
'content' => 'grant_type=client_credentials',
),
);
$context = stream_context_create($options);
$result = json_decode(#file_get_contents('https://api.twitter.com/oauth2/token', false, $context));
if(isset($result->token_type) && $result->token_type == 'bearer')
{
$twitter_bearer_access_token = $result->access_token;
update_option('twitter_bearer_access_token', $twitter_bearer_access_token);
}
else
{
$twitter_bearer_access_token = false;
}
}
Edit #1
I confirm in advance that all variables are the same on both servers, i've outputted and compared them. Only the file_get_contents return a different result.
Also, I tried copying the bearer access token gotten on the 5.3 server to the 5.2 server and the values still match but i keep getting errors about invalid authentication...
Edit #2
More info, it doesn't seem to have anything to do with the headers i send, i added practically all headers except the ones that don't pertain to me such as proxy header. It doesn't have anything to do with PHP being 5.2 or 5.3, tested on our staging server host and switch to 5.2 and still works...
Seems that using cURL works fine. Considering we want to limit our dependencies, we'll just have to resort to having two versions of the code (or eventually use a swapable component to retrieve the distant data)
//Init curl
$request = curl_init();
curl_setopt($request, CURLOPT_SSLVERSION, 3);
curl_setopt($request, CURLOPT_URL, 'https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name='.TWITTER_ACCOUNT.'&count=100');
curl_setopt($request, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$twitter_bearer_access_token));
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
$result = json_decode($content = curl_exec($request));
curl_close($request);
Thats it folks
PS: There still isn't any reason for this to fail, this is just a fallback!

Google authentication from PHP

I know there are a lot of similar questions here in SO but I tried these solutions for hours but they didn´t work for me. I always get a { "error" : "unauthorized_client" }". I want to programmatically refresh my accesstoken to use the Youtube API. I already have gained a refreshtoken.
This is what I´ve come up with:
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'client_secret' => '<mysecret>',
'grant_type' => 'refresh_token',
'refresh_token' => '<my_refresh_token>',
'client_id' => '<my_client_id>.apps.googleusercontent.com',
'redirect_url'=>'<my_redirect_uri>'
));
curl_setopt($ch, CURLOPT_URL, 'https://accounts.google.com/o/oauth2/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
echo var_dump(curl_exec($ch));
Whats wrong with it?
The URL and query params you've indicated look right to me. Seems like this error would come up if the client_id you provide to generate new tokens is different than the client_id provided to obtain the refresh_token.
One thing that might be happening is that if you have generated an access_token and refresh_token using Google's OAuth playground, and then trying to use that refresh_token to generate new tokens -- this will not work. The Google OAuth playground is using different client_ids to make that request, and this will definitely result in the "unauthorized_client" error you've documented.
Temboo has a very concise and easy-to-use OAuth library for Google. You can check it out here: https://www.temboo.com/library/Library/Google/OAuth/.
(Full disclosure: I work at Temboo)

Categories