diff --git a/src/OAuth/OAuth1/Signature/Signature.php b/src/OAuth/OAuth1/Signature/Signature.php index 23711d31..afe27fc7 100644 --- a/src/OAuth/OAuth1/Signature/Signature.php +++ b/src/OAuth/OAuth1/Signature/Signature.php @@ -53,11 +53,8 @@ public function getSignature(UriInterface $uri, array $params, $method = 'POST') { parse_str($uri->getQuery(), $queryStringData); - foreach (array_merge($queryStringData, $params) as $key => $value) { - $signatureData[rawurlencode($key)] = rawurlencode($value); - } - - ksort($signatureData); + $signatureData = array_merge($queryStringData, $params); + $this->ksortRecursive($signatureData); // determine base uri $baseUri = $uri->getScheme() . '://' . $uri->getRawAuthority(); @@ -70,27 +67,12 @@ public function getSignature(UriInterface $uri, array $params, $method = 'POST') $baseString = strtoupper($method) . '&'; $baseString .= rawurlencode($baseUri) . '&'; - $baseString .= rawurlencode($this->buildSignatureDataString($signatureData)); + // The url paramaters are first encoded induvidually by http_build_query, then the result is encoded again. + $baseString .= rawurlencode(http_build_query($signatureData, '', '&', PHP_QUERY_RFC3986)); return base64_encode($this->hash($baseString)); } - /** - * @return string - */ - protected function buildSignatureDataString(array $signatureData) - { - $signatureString = ''; - $delimiter = ''; - foreach ($signatureData as $key => $value) { - $signatureString .= $delimiter . $key . '=' . $value; - - $delimiter = '&'; - } - - return $signatureString; - } - /** * @return string */ @@ -120,4 +102,21 @@ protected function hash($data) ); } } + + /** + * Rescursively sorts an array by key. + * @param string $data + * + * @return string + */ + protected function ksortRecursive(&$array, $sort_flags = SORT_REGULAR) { + if (!is_array($array)) { + return false; + } + ksort($array, $sort_flags); + foreach ($array as &$arr) { + $this->ksortRecursive($arr, $sort_flags); + } + return true; + } } diff --git a/tests/Unit/OAuth1/Signature/SignatureTest.php b/tests/Unit/OAuth1/Signature/SignatureTest.php index 0f1fd062..b1431a4d 100644 --- a/tests/Unit/OAuth1/Signature/SignatureTest.php +++ b/tests/Unit/OAuth1/Signature/SignatureTest.php @@ -41,10 +41,10 @@ public function testSetTokenSecret(): void /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */ @@ -79,10 +79,10 @@ public function testGetSignatureBareUri(): void /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */ @@ -117,10 +117,10 @@ public function testGetSignatureWithQueryString(): void /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */ @@ -155,10 +155,10 @@ public function testGetSignatureWithAuthority(): void /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */ @@ -196,10 +196,10 @@ public function testGetSignatureWithBarePathNonExplicitTrailingHostSlash(): void /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */ @@ -237,10 +237,10 @@ public function testGetSignatureWithBarePathWithExplicitTrailingHostSlash(): voi /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */ @@ -277,10 +277,10 @@ public function testGetSignatureNoTokenSecretSet(): void /** * @covers \OAuth\OAuth1\Signature\Signature::__construct - * @covers \OAuth\OAuth1\Signature\Signature::buildSignatureDataString * @covers \OAuth\OAuth1\Signature\Signature::getSignature * @covers \OAuth\OAuth1\Signature\Signature::getSigningKey * @covers \OAuth\OAuth1\Signature\Signature::hash + * @covers \OAuth\OAuth1\Signature\Signature::ksortRecursive * @covers \OAuth\OAuth1\Signature\Signature::setHashingAlgorithm * @covers \OAuth\OAuth1\Signature\Signature::setTokenSecret */