From b38c45b984e1f4654596a1beae65e56f2eee1785 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 15 Aug 2018 00:26:21 +0300 Subject: [PATCH 1/2] JWTHelper: refactored the QSH creation logic --- src/Helpers/JWTHelper.php | 51 ++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/Helpers/JWTHelper.php b/src/Helpers/JWTHelper.php index cef5d45..0d1164a 100644 --- a/src/Helpers/JWTHelper.php +++ b/src/Helpers/JWTHelper.php @@ -57,7 +57,7 @@ public static function create(string $url, string $method, string $issuer, strin * Create Query String Hash * * More details: - * https://developer.atlassian.com/static/connect/docs/latest/concepts/understanding-jwt.html#creating-token + * https://docs.atlassian.com/DAC/bitbucket/concepts/qsh.html * * @param string $url URL of the request * @param string $method HTTP method @@ -67,40 +67,37 @@ public static function create(string $url, string $method, string $issuer, strin public static function qsh($url, $method) { $method = strtoupper($method); - $parts = parse_url($url); - // Remove "/wiki" part from the path for the Confluence - // Really, I didn't find this part in the docs, but it works - $path = str_replace('/wiki', '', $parts['path']); + $parts = parse_url($url); + $path = $parts['path']; - $canonicalQuery = ''; + // The list of prefixes which must be removed from the path + $prefixes = ['/wiki']; - if (!empty($parts['query'])) { - $query = $parts['query']; - $queryParts = explode('&', $query); - $queryArray = []; + foreach ($prefixes as $prefix) { + $path = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $path); + } - foreach ($queryParts as $queryPart) { - $pieces = explode('=', $queryPart); - $key = array_shift($pieces); - $key = rawurlencode($key); - $value = substr($queryPart, strlen($key) + 1); - $value = rawurlencode($value); - $queryArray[$key][] = $value; - } + // Parse a query into the map of parameters + parse_str($parts['query'], $params); - ksort($queryArray); + // Parameters should be sorted alphabetically + ksort($params); - foreach ($queryArray as $key => $pieceOfQuery) { - $pieceOfQuery = implode(',', $pieceOfQuery); - $canonicalQuery .= $key . '=' . $pieceOfQuery . '&'; - } + $canonicalQuery = http_build_query( + $params, + null, + '&', + PHP_QUERY_RFC3986 + ); - $canonicalQuery = rtrim($canonicalQuery, '&'); - } + $parts = [ + strtoupper($method), + $path, + $canonicalQuery + ]; - $qshString = implode('&', [$method, $path, $canonicalQuery]); - $qsh = hash('sha256', $qshString); + $qsh = hash('sha256', implode('&', $parts)); return $qsh; } From 6d848baff784a99574af8d0d2e731ea0e45baf8b Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 15 Aug 2018 00:30:26 +0300 Subject: [PATCH 2/2] Updated changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77a1f4b..46c6cb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.2.3] - 2018-08-15 + +### Fixed +- Fixed the "Unauthorized" bug on requests with spaced query parameter values (https://github.com/brezzhnev/atlassian-connect-core/issues/9). + ## [1.2.2] - 2018-01-13 ### Added @@ -51,7 +56,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - Package keywords at composer.json -[Unreleased]: https://github.com/brezzhnev/atlassian-connect-core/compare/v1.2.2...HEAD +[Unreleased]: https://github.com/brezzhnev/atlassian-connect-core/compare/v1.2.3...HEAD +[1.2.3]: https://github.com/brezzhnev/atlassian-connect-core/compare/v1.2.2...v1.2.3 [1.2.2]: https://github.com/brezzhnev/atlassian-connect-core/compare/v1.2.1...v1.2.2 [1.2.1]: https://github.com/brezzhnev/atlassian-connect-core/compare/v1.2.0...v1.2.1 [1.2.0]: https://github.com/brezzhnev/atlassian-connect-core/compare/v1.1.0...v1.2.0