url-encode character with Guzzle - php

I work with WordBee API and it works fine on the browser and also with software if I don't use filter which is optional (see below API doc):
http://api.wordbeetranslator.com:32570/projects?token={TOKENID}&filter={FILTER}
API doc example:
http://api.wordbee-translator.com:32570/projects?token=xxx&filter=ClientName='John'
The following is the GET Method I use, implemented with filter:
$resp = $project->request('GET', 'projects', [
'query' => [
'token' => $tokenId,
'filter' => 'ClientName=John'
]
]);
When I send the request with Guzzle I get response '400 Bad Request', probably because of the %3D characters as appear below:
https://api.wordbee-translator.com:32570/projects?token=xxx&filter=ClientName%3DJohn
Note: I may need to url-encode the "=" character in ClientName=John
I found this but I'm not sure how/if to use it in my case:
$request->getQuery()->setEncodingType(false);
How do I fix the request?

Related

Azure/Microsoft Identity Platform - Cannot Retrieve Access Token from Token Endpoint (PHP)

I'm trying to write a custom web app that utilizes the Microsoft Identity Platform to authenticate and authorize users. I'm able to successfully authenticate when calling the /authorize endpoint, and I have access to the "code" token that is returned.
I am now trying to retrieve my access token so that I can make calls to the APIs. Whenever I submit a POST request to the /token endpoint, the server returns a 400 Bad Request error. The header information that is provided contains no valuable information for troubleshooting and there is no JSON response returned so I have no idea where or what the issue is.
I'm making my call as follows:
$clientId = '00000000-0000-0000....'; // Omitted
$tenantId = '00000000-0000-0000....'; // Omitted
$grantType = 'authorization_code';
$scope = urlencode('User.Read');
$code = '......' // Obtained from authentication
$redirect_uri = 'http://localhost/smp/auth/handle';
$clientSecret = '...' // Omitted, set up in Azure App registrations under Certificates and secrets
$resource = 'api://00000000-0000-0000....'; // Omitted, set up in Azure App registrations under Overview -> App ID URI
$url = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token";
$parameters = [
'client_id' => $clientId,
'grant_type' => $grantType,
'scope' => $scope,
'code' => $code,
'redirect_uri' => $redirectUri,
'client_secret' => $clientSecret,
'resource' => $resource
];
$options = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($parameters)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if (!$result) {
exit('an error has occured');
}
PHP returns a warning that reads the following: (tenant id has been omitted):
Warning: file_get_contents(https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/oauth2/v2.0/token): Failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request in C:\xampp\htdocs\smp\application\models\user-model.php on line 261
I've verified everything I can possibly think of.
The client and tenant ids are working (based on the successful authentication request).
The "code" is correctly retrieved from the authentication request.
Redirect Uri is the same as the one used for the authentication request.
I've tried with and without the client_secret variable. It is my understanding that this is actually required in my case.
I've tried with and without the resource variable, which is setup using the default Azure naming convention of "api://".
Please assist! I know I must be missing something but cannot figure it out. Perhaps permissions or additional setup within Azure? I'm not really sure what's wrong with my code/approach but Microsoft Identity Platform/OAuth isn't returning anything for me to work with and/or troubleshoot.
I've figured this out.
Firstly, I modified by $options variable to include the following:
$options = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($parameters),
'ignore_errors' => true
]
];
Adding ignore_errors allowed me to see the returned JSON.
Next, it became apparent that my parameters were not being accepted because I was url-encoding all of them. My client secret, redirect uri, and client ids were all url encoded (this detail was hidden in my original post because it was just a small snippet of a much larger system). By undoing this encoding, my parameters all ended up being accepted. I suppose it makes sense because these values weren't being appended to a url but rather passed as POST values.
Lastly, the "resource" variable was not accepted (indeed, it wasn't required). Not sure if any of this is going to help anyone else but just in case, this was my fix.

Stream Elements PUT Request

Good Afternooon all,
Please can someone give me a example of a PUT request? i have seen a couple online but i can not seam to get any to work.... I am trying to create an app for my live streaming channel, below is what i am trying to use PUT for.
Here is the DEV link to the API: https://dev.streamelements.com
So the URL would be: https://api.streamelements.com/kappa/v2
the PUT i need is the following
/points/{channel}/{user}/{amount}
Media type: application/json
so i understand the url in full if it was a get:
(api.streamelements.com/kappa/v2/points/channe id removed/username removed)
That gives me my points on a selected channel but to add or remove points it has to be a PUT and i have no idea on how to use it, so if anyone could give me some example of the above i could learn from it and do all the other requests myself
Many Thanks for your time
Kev (TADS)
You may need to be familiar with HTTP clients such as Guzzle or other clients that implements Psr7 interface.
In your case your code should looks like:
$client = new GuzzleHttp\Client();
$client->put('https://api.streamelements.com/kappa/v2/REST_OF_URL', [
'headers' => ['X-Foo' => 'Bar'],
'body' => [
'field1' => 'value1',
// ...
],
'timeout' => 10
]);
Obviously I'm assuming that you know how to include the Guzzle library to your project using Composer or standalone include.

PHP OAuth with Reddit

I'm trying to enable "oauth" for Reddit and I'm following the instructions given here - https://github.com/reddit/reddit/wiki/OAuth2
It's all good until I need to make a request for the "access_token".
The documentation says I need to make a "POST" request to the following URL
https://ssl.reddit.com/api/v1/access_token
With the following as POST DATA
grant_type=authorization_code&code=CODE&redirect_uri=URI
It also says
You must supply your OAuth2 client's credentials via HTTP Basic Auth for this request. The "user" is the client_id, the "password" is the client_secret.
And I'm not sure what above means. I've tried a number of different approaches but I'm still getting 401 error. Here's my "POST" code
$data = array('client_id' => self::CLIENT_ID,
'client_secret' => self::CLIENT_SECRET,
'grant_type' => 'authorization_code',
'code' => $_GET['code'],
'redirect_uri' => $my_redirect_url);
$response = Requests::post(self::GET_OAUTH_TOKEN_URL, array(), $data);
any ideas?
You need to additionally provide an "Authorization" header in this format:
"Basic %base_64_encoded_string%"
That base 64 string starts out as "username:password" or in this case "clientid:clientsecret", and then you encode it. So your Authorization header value would end up looking something like this:
"Authorization: Basic d2hhdCB1cCBob21leSBn"

Writing library for Twitter, where am I going wrong?

I'm writing a library to connect to Twitter that uses Requests for PHP. I'm not sure, but I don't think that I'm building the OAuth correctly because I can't authenticate. I've double-checked it, and checked it against another existing library but still can't seem to get it right.
The code is here.
The idea is you instantiate the service, send it config parameters, and before it does the request, it generates the 'Authorization: OAuth xxx' header and adds it to said request.
$twitter = array(
'consumer_key' => '',
'consumer_secret' => '',
'access_token' => '',
'access_token_secret' => '',
'screen_name' => '_hassankhan',
'api_url' => 'https://api.twitter.com/1.1/'
);
$service = new OAuth1AService('Twitter', $twitter['api_url']);
$service->config($twitter);
$service->doGet(
'statuses/user_timeline.json',
array(
'screen_name' => '_hassankhan',
'include_entities' => 'true'
),
array(),
'raw'
);
print($service->getResult());
I would really recommend you to use one of the already made libraries like tmhOAuth which make it really easy to interact with the twitter api.
As for your problem, seems you don't sign your request correctly. At least I could not easily find out if you include all request parameters to create the signature.
The oauth_signature parameter contains a value which is generated by
running all of the other request parameters and two secret values
through a signing algorithm.
Creating the signature is described in this document: https://dev.twitter.com/docs/auth/creating-signature .

Twitter api 1.1 update_with_media

i'm changing my php code to be compatible with new API and i'm stuck with update_with_media.
This is my code:
$image = constant('PATH_UPLOAD').$db_data['post_image'];
$connection = new TwitterOAuth(constant('CONSUMER_KEY'), constant('CONSUMER_SECRET'), $db_data['tw_oauth_token'], $db_data['tw_oauth_secret']);
$content = $connection->OAuthRequest('https://api.twitter.com/1.1/account/verify_credentials.json', 'GET', array());
$twitterInfo = json_decode($content);
$resp_tw = $connection->OAuthRequest('https://api.twitter.com/1.1/statuses/update_with_media.json', 'POST',
array(
'status' => html_entity_decode($db_data['post_text'],ENT_QUOTES,'UTF-8'),
'media[]' => "#{$image}"
)
);
And it returns
{"errors":[{"code":189,"message":"Error creating status"}]}
What might be the problem / what i'm doing wrong?
you can try like this :
$tmhOAuth = new tmhOAuth(array(
'consumer_key' => 'abc',
'consumer_secret' => 'abc',
'user_token' => 'abc',
'user_secret' => 'abc',
));
$response = $tmhOAuth->request('POST', $tmhOAuth->url('1.1/statuses/update_with_media'),
array(
'status' => $message,
'media[]' => file_get_contents($image)
));
if ($response != 200) {
//Do something if the request was unsuccessful
}
there is my code test https://twitter.com/wallapps/status/357137553691906048
Though the question is a few months old, I thought I'd answer it since I spent several hours on making update_with_media work and could not find satisfactory answers online.
Twitter API error messages unfortunately are not that specific. I was able to figure out the foll twitter errors:
"error could not authenticate you" - probably means your OAuth signature base string is not correct
"error incorrect or missing uri" - probably means you are not strictly following the format expected by Twitter in the request body. Could be something as simple as missing a \n in your request body
"error creating status - probably means your status text is encoded when it should not be in the request body of a multipart / form-data request
"Error internal error" - this one indicates nothing useful. It probably means that you have some data that is not encoded when twitter expects it to be or vice versa. It could also mean that you have not included the encoding type in the request body
To make update_with_media work, these tips may help:
The request should have content-type of multipart/form-data
The request body should contain the two elements twitter expects media[] and status in the correct format (RFC 2388)
In addition Twitter server expects \r\n (CR LF) after each portion of the request body. Skipping this causes Twitter to return an error
The media[] data should be base64 encoded and the content-disposition section in the request body should have Content-Transfer-Encoding
OAuth signature base string should be: (see OAuth 1.0A spec for signature) &All oauth_ parameters(name=value) in the Auth header of your request object in alphabetic order, separated by & and encoded

Categories