I have to integrate a web application with an API. The API uses OAuth 1.0 to authorize the requests. I have gone through the documentation at http://oauth.net/core/1.0a/. I have followed all the steps to generate the signature But the server always returns the message "invalid signature".
However, if I put my consumer key, consumer secret, access token and access token secret in POSTMAN. Then the signature that is generated by the POSTMAN is accepted by the server.
That means there is nothing wrong with the server. The problem is in the code that I am using to generate the signature.
Here is the code that I have written after reading the documentation to generate the tokens.
$consumer_key = '__MY_CONSUMER_KEY__';
$secret = '__MY__SECRET_KEY__';
$url = 'http://oauth.example.com/oauth/initiate';
$parameters = 'oauth_callback=oob&oauth_consumer_key='.$consumer_key.'&oauth_nonce='.dechex(time()).'&oauth_signature_method=HMAC-SHA1&oauth_timestamp='.time().'&oauth_version=1.0';
$signature = base64_encode(hash_hmac('sha1', 'GET&'.rawurlencode($url).'&'.rawurlencode($parameters), $secret, true));
$signed_request = $url.'?'.$parameters.'&oauth_signature='.$signature.PHP_EOL;
I know there are some predefined the packages available for this But I want to know what is the actual logic to generate the signature for OAuth 1.0.
Related
I want to get valid link https://bitbucket.org/{username}/rss/feed?token={token} (this is main problem) and then get valid response from this link in CLI.
I know my required parameters, e.g. consumer_key, consumer_secret, request_token_url, authenticate_url, access_token_url.
I tried to use StudioIbizz\OAuth\OAuth1, but is seems to be designed for Browser, not for CLI.
I tried to run:
$this->OAuth = new \StudioIbizz\OAuth\OAuth1($this->consumer_key,$this->consumer_secret);
$requestToken = $this->OAuth->getRequestToken($this->request_token_url,$this->authenticate_url);
$token = $requestToken['oauth_token_secret'];
and paste this $token to my RSS link, but then I see message You must have read access to access the RSS feed. from Bitbucket.
I need Step by Step instructions for serious dummies.
Edit: I tried this:
$accessToken = $this->OAuth->getAccessToken($this->access_token_url,$requestToken['oauth_token_secret'],$requestToken['oauth_token']);
But then I get this:
Fatal error: Uncaught exception 'StudioIbizz\OAuth\OAuthException' with message 'Unexpected HTTP status #400'
I don't see any function related with that on official documentation. Maybe that feature not exists.
For more information, you could use this link:
https://confluence.atlassian.com/bitbucket/use-the-bitbucket-cloud-rest-apis-222724129.html
You could use stevenmaguire's Bitbucket OAuth 2.0 support for the PHP League's OAuth 2.0 Client.
$provider = new Stevenmaguire\OAuth2\Client\Provider\Bitbucket([
'clientId' => '{bitbucket-client-id}',
'clientSecret' => '{bitbucket-client-secret}',
'redirectUri' => 'https://example.com/callback-url'
]);
$token = $_GET['code'];
To get an RSS token for Bitbucket via PHP CLI, you will need to use the OAuth 1.0a protocol to authenticate your request. Here are the steps you can follow:
Install an OAuth library for PHP that can be used in CLI, such as the league/oauth1-client package.
Create a new instance of the OAuth client by passing in your consumer key and consumer secret.
$client = new League\OAuth1\Client\Server\Bitbucket($consumerKey, $consumerSecret);
Get the request token by calling the getTemporaryCredentials method and passing in the callback URL.
$temporaryCredentials = $client->getTemporaryCredentials();
Get the authorization URL by calling the getAuthorizationUrl method and passing in the temporary credentials.
$authorizationUrl = $client->getAuthorizationUrl($temporaryCredentials);
Use this URL to authenticate the request via the browser.
After successful authentication, you will get a verifier code.
Get the access token by calling the getTokenCredentials method and passing in the temporary credentials and the verifier code.
$tokenCredentials = $client->getTokenCredentials($temporaryCredentials, $verifier);
$tokenCredentials = $client->getTokenCredentials($temporaryCredentials, $verifier);
Get the RSS token by calling the getRssToken method and passing in the token credentials
$rssToken = $client->getRssToken($tokenCredentials);
You can use this token to construct your RSS feed link:
https://bitbucket.org/{username}/rss/feed?token={$rssToken}
Note that, this is just a general idea of how to use the OAuth library and it may vary depending on the library you are using. It's also important to check the documentation of that library for more details.
My test request for Amazon Web Service API is returning with the following error:
<ItemSearchErrorResponse xmlns="http://ecs.amazonaws.com/doc/2005-10-05/">
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
</Message>
</Error>
<RequestId>ebe90459-1abd-403e-bfec-6916ebe07e1f</RequestId>
</ItemSearchErrorResponse>
Here is how I arrived at this:
<?php
$private_key = "XXXXXXXXXXXXXXXXXXXXXX";
$date = urlencode(date('Y-m-d\TH:i:s.Z\Z', time()));
$string_to_sign = "GET webservices.amazon.com /onca/xml/ AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXXXXXA&Keywords=Rocket&Operation=ItemSearch&SearchIndex=Toys&Service=AWSECommerceService&Timestamp=".$date."";
$signature = urlencode(base64_encode(hash_hmac("sha256",$string_to_sign, $private_key, True)));
$url = "http://webservices.amazon.com/onca/xml?AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXXXXXX&Keywords=Rocket&Operation=ItemSearch&SearchIndex=Toys&Service=AWSECommerceService&Timestamp=".$date."&Signature=".$signature."";
header("Location: ".$url."");
?>
I basically wanted a signed REST request directly in the url (hence the header function) but left me stuck with the error. I double checked my access id and secret key so I know they are not the one causing the problem. Is this not the right way to produce the signature?
It seems you're trying to use a V2 signature to call the REST API of AWS.
Please refer to the complete AWS REST API call documentation.
My bet is the problem is the absence of SignatureVersion, SignatureMethod and Version in the string before signing. Step five of the documentation linked above shows and example of the string to be signed:
GET\n
elasticmapreduce.amazonaws.com\n
/\n
AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Action=DescribeJobFlows&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2011-10-03T15%3A19%3A30&Version=2009-03-31
This is AWS talk for: "Your credentials are incorrect".
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;
}
I'm currently working with the foursquare API. I downloaded the files from github right here https://github.com/jmathai/foursquare-async. But, when I put my credentials in like my clientId, my client secret, and my redirectUri, it doesn't quite work; it says that there's a redirect uri mismatch. The beginning of the code in the simpleTest.php file looks like this:
ob_start();
require_once 'EpiCurl.php';
require_once 'EpiFoursquare.php';
$clientId = 'CLIENT_ID';
$clientSecret = 'CLIENT_SECRET';
$code = 'CODE';
$accessToken = 'ACCESS_TOKEN';
$redirectUri = 'http://www.thered-line.com/foursquare/simpleTest.php';
$userId = '4855602';
$fsObj = new EpiFoursquare($clientId, $clientSecret, $accessToken);
$fsObjUnAuth = new EpiFoursquare($clientId, $clientSecret);
How to get my $code and $accessToken... ?
This library is for using Foursquare with oAuth. That means that you get your code and access token from part of the oAuth handshake. Foursquare provided you with the client information - the rest is done in the oauth handshake.
When you changed the URL and the user, but kept the code and access token from the original test, you ended up with a code and token that were invalid - you are using the tokens from a handshake that does not have the same data anymore. If you change the test back to how it was on Github, it should run.
Basically, all you need for this lib is the clientID and the Secret - the rest will be done with PHP function calls from the library.
More info
I provide a developer API to a set of data, I want to add 2-legged oauth authentication so I can authenticate developers apps to use the api. Firstly is this the best solution, for this type of authentication?
Secondly, from an implementation/flow point of view, is my understanding correct:
A random developer, goes to my site and uses a 'signup' page, which when submitted I generate them a api key and secret, that can be generated in anyway I wish.
They then use an oauth library like the php one found here to sign their request with these credentials.
$consumer = new OAuthConsumer('thegeneratedkey', 'thegeneratedsecret');
$sig_method = new OAuthSignatureMethod_HMAC_SHA1;
//use oauth lib to sign request
$req = OAuthRequest::from_consumer_and_token($consumer, null, "GET", 'http://mydonaim/api/', array('someapimethod', 'somevalue'));
$sig_method = new OAuthSignatureMethod_HMAC_SHA1();
$req->sign_request($sig_method, $consumer, null);//note: double entry of token
My server then uses the oauth library to check the 'signature' of that request to authenticate the developer app.
$secret = 'secret'; // Ignore this line.
$secret = 'secret'; // Use the $_GET['oauth_consumer_key'] to find the secret in my system.
$consumer = new OAuthConsumer($_GET['oauth_consumer_key'], $secret);
$sig_method = new OAuthSignatureMethod_HMAC_SHA1;
$method = $_SERVER['REQUEST_METHOD'];
$uri = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$sig = $_GET['oauth_signature'];
$req = new OAuthRequest($method, $uri);
//token is null because we're doing 2-leg
$valid = $sig_method->check_signature( $req, $consumer, null, $sig );
Is this correct?
If so, does this authentication have to be done every time a request is made or can I generate a token of some kind to reduce the weight in each HTTP request from developer app to my api?
Firstly is this the best solution, for this type of authentication?
OAuth is designed to allow applications to get user data from a third party service without knowing the user's credentials. As long as that's what you need to do, then OAuth is the right solution for you.
If so, does this authentication have to be done every time a request is made or can I generate a token of some kind to reduce the weight in each HTTP request from developer app to my api?
Both sets of Tokens/Secrets must be provided with every single API request and passed into your OAuth library for authentication. This is how OAuth works. You should not add yet another token into the process, as that would only make things even more complicated, and it would confuse the crap out of any poor developer that finally got OAuth.
Remember, the key sets exist so you can revoke access to an entire application, and so users can do the same, assuming you give them an interface to do so. Both sets are included with each request so your application can check them for validity.
Don't worry about the "weight" of an HTTP request unless you've performed benchmarking and profiling and have determined that the size of requests is something you need to work on. I can pretty much guarantee that it's a non-issue.