diff --git a/CHANGELOG.md b/CHANGELOG.md index b0691de9..364c89d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## Unreleased +- PATCH: Fix the issue "Get Current Session ID process from Post Purchase Extension Token" ## v5.1.0 - 2023-07-11 diff --git a/src/Auth/OAuth.php b/src/Auth/OAuth.php index 8ee417a3..07c26cdd 100644 --- a/src/Auth/OAuth.php +++ b/src/Auth/OAuth.php @@ -12,6 +12,7 @@ use Shopify\Exception\CookieSetException; use Shopify\Exception\HttpRequestException; use Shopify\Exception\InvalidArgumentException; +use Shopify\Exception\InvalidJwtPayloadException; use Shopify\Exception\InvalidOAuthException; use Shopify\Exception\MissingArgumentException; use Shopify\Exception\OAuthSessionNotFoundException; @@ -232,7 +233,15 @@ public static function getCurrentSessionId(array $rawHeaders, array $cookies, bo } $jwtPayload = Utils::decodeSessionToken($matches[1]); - $shop = preg_replace('/^https:\/\//', '', $jwtPayload['dest']); + + if (!empty($jwtPayload['dest'])) { + $shop = preg_replace('/^https:\/\//', '', $jwtPayload['dest']); + } elseif (!empty($jwtPayload['input_data']->shop->domain)) { + $shop = preg_replace('/^https:\/\//', '', $jwtPayload['input_data']->shop->domain); + } else { + throw new InvalidJwtPayloadException('Missing shop value in JWT payload'); + } + if ($isOnline) { $currentSessionId = self::getJwtSessionId($shop, $jwtPayload['sub']); } else { diff --git a/src/Exception/InvalidJwtPayloadException.php b/src/Exception/InvalidJwtPayloadException.php new file mode 100644 index 00000000..2fa398f7 --- /dev/null +++ b/src/Exception/InvalidJwtPayloadException.php @@ -0,0 +1,9 @@ +domain = "https://exampleshop.myshopify.com"; + $inputData = new stdClass(); + $inputData->shop = $shop; + + $payload = [ + "iss" => "https://exampleshop.myshopify.com/admin", + "sub" => "42", + "input_data" => $inputData, + "iat" => 1591764998, + ]; + + return JWT::encode($payload, Context::$API_SECRET_KEY, 'HS256'); + } + + private function encodeInvalidJwtPayloadFromPostPurchaseExtension(): string + { + $payload = [ + "iss" => "https://exampleshop.myshopify.com/admin", + "sub" => "42", + "iat" => 1591764998, + ]; + + return JWT::encode($payload, Context::$API_SECRET_KEY, 'HS256'); + } + + + public function testGetCurrentSessionIdFromPostPurchaseTokenForOnlineShop() + { + $token = $this->encodeJwtPayloadFromPostPurchaseExtension(); + + $currentSessionId = OAuth::getCurrentSessionId(['Authorization' => "Bearer $token"], [], true); + $this->assertEquals('exampleshop.myshopify.com_42', $currentSessionId); + } + + public function testGetCurrentSessionIdFromPostPurchaseTokenForOfflineShop() + { + $token = $this->encodeJwtPayloadFromPostPurchaseExtension(); + + $currentSessionId = OAuth::getCurrentSessionId(['Authorization' => "Bearer $token"], [], false); + $this->assertEquals('offline_exampleshop.myshopify.com', $currentSessionId); + } + + public function testGetCurrentSessionIdFromPostPurchaseTokenInvalidJwtPayloadException() + { + $token = $this->encodeInvalidJwtPayloadFromPostPurchaseExtension(); + + $this->expectException(InvalidJwtPayloadException::class); + $this->expectExceptionMessage('Missing shop value in JWT payload'); + $currentSessionId = OAuth::getCurrentSessionId(['Authorization' => "Bearer $token"], [], true); + } + }