OAuth 1.0a Implementation with PHP Pecl - Custom Signature (Fitbit) - php

I had an implementation of OAuth working with Fitbit to pull data from fitbit's service. However they recently updated their service and now the request is failing whenever I try to get an access token.
They have made the following statement about the new requirement:
The solution is to OAuth sign the requests to <https://api.fitbit.com/oauth/request_token> and <https://api.fitbit.com/oauth/access_token> in a similar manner that all other calls to the Fitbit API are signed.
Requests to <https://api.fitbit.com/oauth/request_token> need to be signed with your application's consumer key and secret.
Requests to <https://api.fitbit.com/oauth/access_token> need to be signed with your application's consumer key and secret and the oauth_token and oauth_verifier received from the authorization callback.
I am using the PHP PECL OAuth library for OAuth requests. However I can't find a way to add additional parameters to the signature. I am trying the following but I'm not sure that this is the correct way to update the OAuth Signature:
$params['consumer_key'] = $this->consumer_key;
$params['consumer_secret'] = $this->consumer_secret;
$params['oauth_token'] = $this->oauth_token;
$params['oauth_verifier'] = $_REQUEST['oauth_verifier'];
$this->signature = $this->oauth->generateSignature('GET', $this->access_url, $params);
$this->access_token = $this->oauth->getAccessToken($this->access_url, $this->signature, $_REQUEST['oauth_verifier']);
The OAuth error I get is:
401
Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)
oauthoauth_signatureInvalid signature: FfvYDv5MSOfwcOwLZBJa0TlKS4Q=false
The signature which is stored from the code above shows that the proper signature should be:
[signature] => wlfzqPs4aEkTkHfqyaO65D/RW6o=
This is the "Headers Sent" piece of the debug information:
[headers_sent] => Authorization: OAuth oauth_session_handle="Frdnxw8oHe3BgNVi0Fy4jBXrZko%3D",
oauth_verifier="ss6nmke8elf3so66jg3auued49",
oauth_consumer_key="(my key)",
oauth_signature_method="HMAC-SHA1",
oauth_nonce="30463910852ea5cc2d04e60.71895372",
oauth_timestamp="1391090882",
oauth_version="1.0",
oauth_token="2cabd6beab341e332bdf8e522b6019ef",
oauth_signature="hULwWcQOl%2F8aYjh0YjR843iVXtA%3D"
I can't find anything in the documentation which explains how I can set the signature for OAuth to use with it's request. Any Help would be greatly appreciated!!!
Please let me know if you need more information!

I have found the issue.
It turns out I was not saving the oauth_token_secret being handed back and I was instead using the consumer secret.
Once I updated this, the process ran as expected.

Related

Can only get access token for QuickBooks API once

I'm using PHPoAuthLib in order to connect to the QuickBooks API per their example
When I follow their example, the first request that I make to the API works perfectly:
$result = json_decode($quickbooksService->request($url));
echo 'result: <pre>' . print_r($result, true) . '</pre>';
However in their example they use $_GET['oauth_token'] and $_GET['oauth_verifier'] to request an access token, and these values are only available on the $_GET server variable during the single callback from QuickBooks Online immediately after my app has been authorized.
For future requests there are no such examples on PHPoAuthLib's docs, so I tried a quick homebrew solution:
Save the response from QBO somewhere
if (!empty($_GET['oauth_token']) {
file_put_contents("token.txt", json_encode([
'oauth_token' => $_GET['oauth_token'],
'oauth_verifier' => $_GET['oauth_verifier'],
'realm_id' => $_GET['realmId']
]));
}
Use that response again later
$token = json_decode(file_get_contents("token.txt"));
$quickbooksService->requestAccessToken(
$token->oauth_token,
$token->oauth_verifier
// $token->getRequestTokenSecret() is not necessary - it will be automatically populated
);
// At this point my app crashes and return a 500 error
// Further code does not run
The error I receive is:
TokenResponseException in StreamClient.php line 68:
Failed to request resource. HTTP Code: HTTP/1.1 401 Unauthorized
Remember that the token and verifier work perfectly if I use them immediately after the app is authorized. If I save them to a file and attempt to re-use them 30 seconds later, this happens.
I think it might be a fundamental misconception about OAuth 1.0
I don't think what you have is a correct OAuth implementation. Have you read the OAuth spec and implemented as it's defined there?
Once you have a request token and a verifier, you use those to get an access token.
That access token is then good for 6 months.
It looks like you're trying to use a short-lived request token to continually fetch access tokens instead. That won't work.
i.e. If you're doing this everytime you want to make another request:
$quickbooksService->requestAccessToken(
Then you're doing something wrong. You should be doing that ONCE every 6 months, and that's it.
Working code here:
https://github.com/consolibyte/quickbooks-php/blob/master/QuickBooks/IPP/IntuitAnywhere.php
https://github.com/consolibyte/quickbooks-php/blob/master/QuickBooks/IPP/OAuth.php
https://github.com/consolibyte/quickbooks-php
Spec is here:
http://oauth.net/core/1.0a/#auth_step3

Generating Signatures for the Authentication Header in PHP - Paypal

Having recently finished the process of having created the script that retrieves permissions from a account holder I now find that I have to convert the retrieved access token and token secret (from the GetAccessToken response) to the API signature in order to create a X-PAYPAL-AUTHORIZATION header.
The X-PAYPAL-AUTHORIZATION header contains:
A timestamp
The access token from the GetAccessToken response
A signature generated from the following information:
Your API username
Your API password
The access token from the GetAccessToken response
The token secret from the GetAccessToken response
The endpoint for the PayPal API operation's request, such as https://api.paypal.com/nvp
HTTPS delivery method, such as POST
Request parameters associated with the request
The problem is I can't find how to generate the signature. There are no guides in PHP (JAVA and Ruby).
I did however note the line in the guide I followed (first link) to retrieve the permissions:
PayPal provides SDKs that you can use to generate authentication header signatures for Java, PHP, and .NET. When you use the SDK, you will get two values, such as the following:
But what followed was the JAVA guide and I could not find anything amongth Paypal's SDKs.
Any help would be greatly appreciated!
This documentation actually cuts out the function from their PHP SDK that should do it for you.
private function generateAuthString($apiCred, $accessToken, $tokenSecret, $endpoint)
{
$callerUid = $apiCred->getUserName();
$callerPswd = $apiCred->getPassword();
$auth = new AuthSignature();
$response = $auth->genSign($callerUid,$callerPswd,$accessToken,$tokenSecret,'POST',$endpoint);
$authString =
"token=".$accessToken.
",signature=".$response['oauth_signature'].
",timestamp=".$response['oauth_timestamp'];
return $authString;
}

OAuth API call parameters not specific

I've been working for the first time with OAuth lately, I've gotten the access token fine along with everything before it but I've stumbled with what I assumed would be the easiest part :(
The API call requires a parameter which isn't very specific, they just call it 'oauth'. I'm already putting my access token and secret into the signature, what should be in the 'oauth' parameter?
Here's what I'm talking about.
Thanks!
For oAuth 1.0 (Twitter) Here's what an oAuth HTTP header may look like:
Authorization: OAuth oauth_consumer_key="*****", oauth_nonce="fcde5bfc94d489c307f59aa384df9ef3", oauth_signature="tWE9gf3Dw0rBiKkN%2BcgO%2Fz%2FE%2FjA%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1335428402", oauth_token="*****", oauth_version="1.0"

Getting an OAuth access token (not language specific) - same issue for Flickr and Tumblr, but not Twitter

I'm making the huge mistake of writing my own OAuth library and wrapper classes in PHP. Everything works wonderfully for Twitter's OAuth implementation, but I fail on signing the access_token step for both Tumblr and Flickr.
The ONLY difference in that step, is now I have oauth_token and oauth_verifier parameters. I'm using the Authorization header, and the only problem I can think of is that there are some character encoding issues, but I'm not sure.
Base string (broken for clarity):
POST&
http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Faccess_token&
oauth_consumer_key%3Deeedfcd4c46a2c12080f58eb90a974d8
%26oauth_nonce%3D322190b47ca680d053338724ad1cc56d35d3e7b5
%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1322981994
%26oauth_token%3D72157628270097303-18aa378b4ab02af3
%26oauth_verifier%3Dec7811503fdd4380
%26oauth_version%3D1.0
This is exactly what Flickr expects (they tell me so in the error response), which leads me to believe the signature is the problem.
Authorization header (also broken for clarity):
Authorization: OAuth
oauth_consumer_key="eeedfcd4c46a2c12080f58eb90a974d8",
oauth_nonce="322190b47ca680d053338724ad1cc56d35d3e7b5",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1322981994",
oauth_token="72157628270097303-18aa378b4ab02af3",
oauth_verifier="ec7811503fdd4380",
oauth_version="1.0",
oauth_signature="LYJtgHetQWNKX3rtQlSs643FdWY%3D"
And Flickr's response:
oauth_problem=signature_invalid&
debug_sbs=POST&
http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Faccess_token&
oauth_consumer_key%3Deeedfcd4c46a2c12080f58eb90a974d8
%26oauth_nonce%3D322190b47ca680d053338724ad1cc56d35d3e7b5
%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1322981994
%26oauth_token%3D72157628270097303-18aa378b4ab02af3
%26oauth_verifier%3Dec7811503fdd4380
%26oauth_version%3D1.0
There are no GET or POST parameters. Everything seems to be escaped correctly from what I see here. The signing works for the request_token step (and for Twitter, for ANY request). I've verified that my server clock is within a second of theirs. Am I missing something obvious? How would you go about diagnosing this?
I'll answer my own question.
There were a few discrepancies between the different oauth service provider implementations:
Twitter
Expects oauth_callback on request_token step
Doesn't return oauth_token_secret until access_token response
Therefore, there's an empty oauth_token_secret in signing the access_token request
Flickr & Tumblr
Expect oauth_callback on authenticate (i.e. authorize) step
Return oauth_token_secret on request_token step (and expect you to remember it and use it to sign access_token request)
Youtube (and other Google OAuth service providers):
Expects Google-proprietary "scope" on request_token step
Expects oauth_callback on authenticate (i.e. OAuthAuthorizeToken) step
Doesn't seem to like oauth_token passed in Authorization header in the access_token step (responds with "token invalid" due to required double-encoding in base string). Pass it in the post body or query string instead.

PHP OAuthProvider library -- invalid_signature, OAuth Flow... just confused

I'm trying to use the OAuthProvider library from PHP.net and of course, it's not documented. I've followed Rasmus' tutorial and I've followed djpate.com's tutorial and neither of them to work for me and Rasmus doesn't link to any source, the source he does link to for examples is confusing and of course, doesn't work when ran.
I seem to always get a "signatures do not match" error which I don't understand really, because I've followed the tutorials to a T.
What's the flow supposed to be anyway?
1. Create consumer key/secret. Check.
2. Get the access token? I get errors -- Where does the signature come from?
3. Get the request token? I get error
I'm trying to create an OAuthProvider so that I can create 1 consumer account that can call my API remotely and it seems like this is very poorly documented for a beginner... in PHP land anyway.
If anyone has any working OAuthProvider libraries or can explain this to me in more detail I would greatly appreciate it.
Thanks in advance.
http://oauth.net/core/1.0a/ tells you the basic flow.
A consumer gets a consumer key and secret.
The consumer gets a request token.
The consumer redirects the user to the provider's authentication endpoint.
The user signs the request token (or doesn't).
The consumer swaps a authentication token for their signed request token.
The consumer uses their authentication token to access protected information.
http://oauth.net/core/1.0a/#signing_process describes how a request is signed.
"The signature process encodes the Consumer Secret and Token Secret
into a verifiable value which is included with the request."
If you are using the pecl oauth/oauthprovider code, the signature is automatically generated on both sides for you (undocumented but true). You can check to see what the signature is by putting the following in the oauthexception catch section in the provider:
catch (OAuthException $E)
{
error_log(print_r($this->provider, true));
echo OAuthProvider::reportProblem($E);
$this->oauth_error = true;
}
and the following in your oauth consumer oauthexception catch section:
catch(OAuthException $E)
{
error_log(print_r($oauth, true));
echo $E->getMessage();
}
In this way you can check your error logs to find out what the signatures are and whether they do in fact not match.
I am having similar error. This seems to be caused, in my case, due to a signature mismatch in http vs https url.
I would check if you are getting re-directed between http and https.

Categories