diff --git a/src/Utils.php b/src/Utils.php index f52d502..ef76657 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -15,8 +15,8 @@ class Utils public static function parseJwt($jwt) { $tokenParts = explode('.', $jwt); - $header = json_decode(base64_decode($tokenParts[0]), true); - $payload = json_decode(base64_decode($tokenParts[1]), true); + $header = json_decode(self::base64url_decode($tokenParts[0]), true); + $payload = json_decode(self::base64url_decode($tokenParts[1]), true); return ['header' => $header, 'payload' => $payload]; } @@ -28,11 +28,11 @@ public static function parseJwt($jwt) */ public static function generateJwt($headers, $payload, $key) { - $encodedHeaders = self::base64urlEncode(json_encode($headers)); - $encodedPayload = self::base64urlEncode(json_encode($payload)); + $encodedHeaders = self::base64url_encode(json_encode($headers)); + $encodedPayload = self::base64url_encode(json_encode($payload)); $signature = hash_hmac('SHA256', "$encodedHeaders.$encodedPayload", $key, true); - $encodedSignature = self::base64urlEncode($signature); + $encodedSignature = self::base64url_encode($signature); return "$encodedHeaders.$encodedPayload.$encodedSignature"; } @@ -51,21 +51,27 @@ public static function isJwtValid($jwt, $timeFn, $key) $tokenSignature = $tokenParts[2]; // check the expiration time - note this will cause an error if there is no 'exp' claim in the jwt - $expiration = json_decode(base64_decode($payload))->exp; + $expiration = json_decode(self::base64url_decode($payload))->exp; $isTokenExpired = $expiration <= $timeFn(); // build a signature based on the header and payload using the secret $signature = hash_hmac('SHA256', $header.'.'.$payload, $key, true); - $isSignatureValid = self::base64urlEncode($signature) === $tokenSignature; + $isSignatureValid = self::base64url_encode($signature) === $tokenSignature; return $isSignatureValid && ! $isTokenExpired; } - public static function base64urlEncode($str) + public static function base64url_encode($str): string { return rtrim(strtr(base64_encode($str), '+/', '-_'), '='); } + /** + * https://www.php.net/manual/en/function.base64-encode.php#127544 + */ + public static function base64url_decode($data) { + return base64_decode(strtr($data, '-_', '+/'), true); + } const SOCKET_ID_ERROR = "please make sure to send base64 encoded json with " ."'connectionKey' and 'clientId' as keys. 'clientId' is null if connection is not identified"; @@ -76,10 +82,9 @@ public static function base64urlEncode($str) public static function decodeSocketId($socketId) { $socketIdObject = null; if ($socketId) { - try { - $socketIdObject = json_decode(base64_decode($socketId)); - } catch (\Exception $e) { - throw new AblyException("SocketId decoding failed, ".self::SOCKET_ID_ERROR, 0, $e); + $socketIdObject = json_decode(self::base64url_decode($socketId)); + if (!$socketIdObject) { + throw new AblyException("SocketId decoding failed, ".self::SOCKET_ID_ERROR); } if (!isset($socketIdObject->connectionKey)) { throw new AblyException("ConnectionKey is missing, ".self::SOCKET_ID_ERROR); diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 975462b..bdb6ad1 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -26,4 +26,13 @@ public function testGenerateAndValidateToken() $jwtIsValid = Utils::isJwtValid($jwtToken, $timeFn, 'efgh'); self::assertTrue($jwtIsValid); } + + public function testValidateDecodingSocketId() { + $socketId = new \stdClass(); + $socketId->connectionKey = 'key'; + $socketId->clientId = 'clientId'; + $socketIdObject = Utils::decodeSocketId(Utils::base64url_encode(json_encode($socketId))); + self::assertEquals('key', $socketIdObject->connectionKey); + self::assertEquals('clientId', $socketIdObject->clientId); + } }