问题
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 grant_type
, client_id
, client_secret
and 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 guzzle/oauth-subscriber
package.
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 consumer_secret
and client_secret
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.
EDIT:
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:
POST&https%3A%2F%2Faccount.api.here.com%2Foauth2%2Ftoken&grant_type%3Dclient_credentials%26oauth_consumer_key%3DXXbXbXbXbXbXbXb%26oauth_nonce%3DrZNNSZGOOIHFFtLboCjdAheCmKJmOYSp%26oauth_signature_method%3DHMAC-SHA256%26oauth_timestamp%3D1583640503%26oauth_version%3D1.0
I've also created a new gist here with my updates to create this $baseString
Cheers, Matt
回答1:
I created a gist that works. Some suggestion:
- 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. https://gist.github.com/roberto-butti/736c38c796ede70c719f6a21a752c971
This documentation was very useful: https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/creating-a-signature
回答2:
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
来源:https://stackoverflow.com/questions/60584192/here-rest-api-oauth-2-0-token-request-with-a-1-0-header-error