HERE REST API OAuth 2.0 令牌请求(带有 1.0 header)错误
HERE REST API OAuth 2.0 Token Request (with a 1.0 header) Error
我一直在努力让我的 PHP 应用程序创建一个成功的令牌请求,因为根据文档 here
最终设法让它与 Postman 一起工作
显然 API 正在使用 OAuth 2.0,这就是为什么我希望发送 grant_type
、client_id
、client_secret
和 expires_in
(如果我不要指定这些字段之一,然后 API 会成功地告诉我它丢失了)。
现在我遇到的问题是我必须生成的这个 OAuth 1.0 授权 Header,邮递员似乎没有问题这样做,但是试图在 PHP 中做到这一点我刚收到 API 返回的关于签名不匹配的错误:
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."
]
我尝试了各种调试,其中很多都给我不同的错误,然后我一直回到这个错误,所以签名一定是问题所在。
我创建了以下 class here 来处理生成 header,从 guzzle/oauth-subscriber
包中的 class 获得了一些指导。
这是正在生成的请求 header 的示例:
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""
]
请求body:
array:4 [
"grant_type" => "client_credentials"
"client_id" => "XXXXXXXXXXXX"
"client_secret" => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"expires_in" => 87000
]
已替换敏感信息,但 consumer_key
是正确的,与 client_id
的值相同,consumer_secret
和 client_secret
的值相同
无论我如何尝试更改 signUsingHmac()
方法来更改签名,它都不起作用,对我来说一切正常 D:
有人有什么想法吗?
如果我能让它很好地工作,我会把它拉出到包中,使 PHP 中的 API 的身份验证不那么痛苦。
编辑:
我尝试完全按照文档 here 中显示的方式形成签名,但不幸的是它仍然没有用,这就是我的 $baseString
在传递到哈希方法时的样子:
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
我还创建了一个新的要点 here 我的更新创建了这个 $baseString
干杯,
马特
似乎 access_id 和 access_key 都在请求 body 中传递,"grant_type" => "client_credentials"
只需要在 body 中,而access_id and access_key
应在 header 中传递。你可以先在邮递员里试试,如果成功了,请回复
我创建了一个有效的要点。
一些建议:
- 所有值都需要 urlenconde()
- 您需要使用的字符串
对于签名,请求需要包括:方法(大写)& URL
(urlecode) & 参数列表 (url 编码)
- 签名密钥是您的消费者密钥(url编码)后跟 &。这是因为通常您的签名密钥需要我的消费者秘密和秘密令牌。在这种情况下,我们没有秘密令牌
对于签名基本字符串的参数列表,您需要包括所有 oauth_ 参数和您的 grant_type,因为您还需要包括 body 参数。这些key的排序很关键
部分代码PHP代码:
$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;
我创建了一个有效的 GIST,您唯一需要更改的是 $keyId 和 $keySecret。
https://gist.github.com/roberto-butti/736c38c796ede70c719f6a21a752c971
这份文档非常有用:https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/creating-a-signature
我一直在努力让我的 PHP 应用程序创建一个成功的令牌请求,因为根据文档 here
最终设法让它与 Postman 一起工作显然 API 正在使用 OAuth 2.0,这就是为什么我希望发送 grant_type
、client_id
、client_secret
和 expires_in
(如果我不要指定这些字段之一,然后 API 会成功地告诉我它丢失了)。
现在我遇到的问题是我必须生成的这个 OAuth 1.0 授权 Header,邮递员似乎没有问题这样做,但是试图在 PHP 中做到这一点我刚收到 API 返回的关于签名不匹配的错误:
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."
]
我尝试了各种调试,其中很多都给我不同的错误,然后我一直回到这个错误,所以签名一定是问题所在。
我创建了以下 class here 来处理生成 header,从 guzzle/oauth-subscriber
包中的 class 获得了一些指导。
这是正在生成的请求 header 的示例:
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""
]
请求body:
array:4 [
"grant_type" => "client_credentials"
"client_id" => "XXXXXXXXXXXX"
"client_secret" => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"expires_in" => 87000
]
已替换敏感信息,但 consumer_key
是正确的,与 client_id
的值相同,consumer_secret
和 client_secret
无论我如何尝试更改 signUsingHmac()
方法来更改签名,它都不起作用,对我来说一切正常 D:
有人有什么想法吗?
如果我能让它很好地工作,我会把它拉出到包中,使 PHP 中的 API 的身份验证不那么痛苦。
编辑:
我尝试完全按照文档 here 中显示的方式形成签名,但不幸的是它仍然没有用,这就是我的 $baseString
在传递到哈希方法时的样子:
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
我还创建了一个新的要点 here 我的更新创建了这个 $baseString
干杯, 马特
似乎 access_id 和 access_key 都在请求 body 中传递,"grant_type" => "client_credentials"
只需要在 body 中,而access_id and access_key
应在 header 中传递。你可以先在邮递员里试试,如果成功了,请回复
我创建了一个有效的要点。 一些建议:
- 所有值都需要 urlenconde()
- 您需要使用的字符串 对于签名,请求需要包括:方法(大写)& URL (urlecode) & 参数列表 (url 编码)
- 签名密钥是您的消费者密钥(url编码)后跟 &。这是因为通常您的签名密钥需要我的消费者秘密和秘密令牌。在这种情况下,我们没有秘密令牌
对于签名基本字符串的参数列表,您需要包括所有 oauth_ 参数和您的 grant_type,因为您还需要包括 body 参数。这些key的排序很关键
部分代码PHP代码:
$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;
我创建了一个有效的 GIST,您唯一需要更改的是 $keyId 和 $keySecret。 https://gist.github.com/roberto-butti/736c38c796ede70c719f6a21a752c971
这份文档非常有用:https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a/creating-a-signature