I’ve been trying to get my PHP application to create a successful token request since finally managing to get it working with Postman as per the docs here
Apparently the API is using OAuth 2.0 which is why I expect to send up
expires_in (if I don’t specify one of these fields then the API will successfully tell me it is missing).
Now the problem I am having is with this OAuth 1.0 Authorization Header that I am having to generate, which Postman seems to have no issues doing so, however trying to do it in PHP I am just getting an error returned from the API about a signature mismatch:
array:6 [ "errorId" => "ERROR-fde4f0f1-9d5c-43fd-80eb-056cbf2c3259" "httpStatus" => 401 "errorCode" => 401300 "message" => "Signature mismatch. Authorization signature or client credential is wrong." "error" => "invalid_client" "error_description" => "errorCode: '401300'. Signature mismatch. Authorization signature or client credential is wrong." ]
I’ve tried various debugging, a lot of which gives me different errors then I keep landing back on this one so the signature must be the problem.
I created the following class here to handle generating a header, getting some guidance from the class in the
Here is an example of the request headers being generated:
array:2 [ "Content-Type" => "application/x-www-form-urlencoded" "Authorization" => "OAuth oauth_consumer_key="XXXXXXXXXXXX",oauth_signature_method="HMAC-SHA256",oauth_timestamp="1583629976",oauth_nonce="Br2HsCVzsaEe3KswBhtCzsSxjUDWgX56",oauth_version="1.0",oauth_signature="G7%2B5f2v2Kdx3rp%2B28DcuJRBvhi9H7fHC1mFLqJIgmMc%3D"" ]
And the request body:
array:4 [ "grant_type" => "client_credentials" "client_id" => "XXXXXXXXXXXX" "client_secret" => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "expires_in" => 87000 ]
Sensitive details replaced but
consumer_key is correct and thats the same value as
client_id and the same goes for
No matter how I try and alter the
signUsingHmac() method to change the signature, it doesn’t work and it all looks fine to me D:
Anyone got any ideas?
If I can get this working nicely I will pull it out into package to make the auth for this API in PHP a lot less painful.
I tried forming the signature exactly like shown in the docs here but to unfortunately it still hasn’t worked, this is what my
$baseString looked like when passing into the hash method:
I’ve also created a new gist here with my updates to create this
I created a gist that works.
- all values need to be urlenconde()
- the string that you need to use
for signign the request needs to include: method (uppercase) & URL
(urlecode) & list of parameters (url encoded)
- the signing key is your consumer key secret (urlencode) followed by &. This because usually your signing key needs to me consumer secret & secret token. In this case we don’t have secret token
For the list of parameters for your signature base string you need to include all oauth_ parameter and your grant_type because you need to include also the body parameter. The sorting of these keys is crucial
some code PHP code:
$keyId = getenv('HERE_API_KEY_ID'); $keySecret = getenv('HERE_API_KEY_SECRET'); $httpBody = [ "grant_type" => "client_credentials" ]; $httpMethod = "POST"; $httpUrl = 'https://account.api.here.com/oauth2/token'; $oauthNonce = mt_rand(); $oauthTimestamp = time(); $oauthSignatureMethod= "HMAC-SHA256"; $oauthVersion = "1.0"; $baseString = $httpMethod."&". urlencode($httpUrl); $oauth1Param = [ 'oauth_consumer_key' => $keyId, 'oauth_signature_method' => $oauthSignatureMethod, 'oauth_timestamp' => $oauthTimestamp, 'oauth_nonce' => $oauthNonce, 'oauth_version' => $oauthVersion ]; $paramString = "grant_type=client_credentials&". "oauth_consumer_key=". urlencode($oauth1Param['oauth_consumer_key']). "&oauth_nonce=". urlencode($oauth1Param['oauth_nonce']). "&oauth_signature_method=". urlencode($oauth1Param['oauth_signature_method']). "&oauth_timestamp=". urlencode($oauth1Param['oauth_timestamp']). // "&oauth_token=". "&oauth_version=". urlencode($oauth1Param['oauth_version']) ; echo $paramString.PHP_EOL; $baseString = $baseString . "&" . urlencode($paramString); echo $baseString . PHP_EOL; $signingKey= urlencode($keySecret) . "&"; $signature = urlencode( base64_encode( hash_hmac( 'sha256', $baseString, $signingKey, true ) ) ); $oauth1Param['oauth_signature'] = $signature; echo "RUNTIME SIGNATURE : " . $signature .PHP_EOL;
I create a GIST that works, the only thing that you need to change is $keyId and $keySecret.
This documentation was very useful: https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/creating-a-signature
It seems the access_id and access_key both are getting passed in the request body,
"grant_type" => "client_credentials" only needs to be in the body, while
access_id and access_key should be passed in header. you can try first that in postman, if it does work out, please revert