diff options
-rw-r--r-- | Authentication/JWT.php | 75 | ||||
-rwxr-xr-x | run-tests.sh | 1 | ||||
-rw-r--r-- | tests/JWTTest.php | 4 |
3 files changed, 30 insertions, 50 deletions
diff --git a/Authentication/JWT.php b/Authentication/JWT.php index 54d0eff..c0c965b 100644 --- a/Authentication/JWT.php +++ b/Authentication/JWT.php @@ -15,9 +15,7 @@ */ class JWT { - public static $only_method = 'HS256'; - - public static $methods = array( + public static $supported_algs = array( 'HS256' => array('hash_hmac', 'SHA256'), 'HS512' => array('hash_hmac', 'SHA512'), 'HS384' => array('hash_hmac', 'SHA384'), @@ -27,9 +25,9 @@ class JWT /** * Decodes a JWT string into a PHP object. * - * @param string $jwt The JWT - * @param string|Array|null $key The secret key, or map of keys - * @param bool $verify Don't skip verification process + * @param string $jwt The JWT + * @param string|Array|null $key The secret key, or map of keys + * @param bool $algs List of supported verification algorithms * * @return object The JWT's payload as a PHP object * @@ -43,7 +41,7 @@ class JWT * @uses jsonDecode * @uses urlsafeB64Decode */ - public static function decode($jwt, $key = null, $verify = true) + public static function decode($jwt, $key = null, $algs = array()) { $tks = explode('.', $jwt); if (count($tks) != 3) { @@ -57,10 +55,13 @@ class JWT throw new UnexpectedValueException('Invalid claims encoding'); } $sig = JWT::urlsafeB64Decode($cryptob64); - if ($verify) { + if (!empty($key)) { if (empty($header->alg)) { throw new DomainException('Empty algorithm'); } + if (empty(self::$supported_algs[$header->alg])) { + throw new DomainException('Algorithm not supported'); + } if (is_array($key)) { if (isset($header->kid)) { $key = $key[$header->kid]; @@ -105,16 +106,16 @@ class JWT * * @param object|array $payload PHP object or array * @param string $key The secret key - * @param string $algo The signing algorithm. Supported + * @param string $alg The signing algorithm. Supported * algorithms are 'HS256', 'HS384' and 'HS512' * * @return string A signed JWT * @uses jsonEncode * @uses urlsafeB64Encode */ - public static function encode($payload, $key, $algo = 'HS256', $keyId = null) + public static function encode($payload, $key, $alg = 'HS256', $keyId = null) { - $header = array('typ' => 'JWT', 'alg' => $algo); + $header = array('typ' => 'JWT', 'alg' => $alg); if ($keyId !== null) { $header['kid'] = $keyId; } @@ -123,7 +124,7 @@ class JWT $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload)); $signing_input = implode('.', $segments); - $signature = JWT::sign($signing_input, $key, $algo); + $signature = JWT::sign($signing_input, $key, $alg); $segments[] = JWT::urlsafeB64Encode($signature); return implode('.', $segments); @@ -134,24 +135,24 @@ class JWT * * @param string $msg The message to sign * @param string|resource $key The secret key - * @param string $method The signing algorithm. Supported algorithms + * @param string $alg The signing algorithm. Supported algorithms * are 'HS256', 'HS384', 'HS512' and 'RS256' * * @return string An encrypted message * @throws DomainException Unsupported algorithm was specified */ - public static function sign($msg, $key, $method = 'HS256') + public static function sign($msg, $key, $alg = 'HS256') { - if (empty(self::$methods[$method])) { + if (empty(self::$supported_algs[$alg])) { throw new DomainException('Algorithm not supported'); } - list($function, $algo) = self::$methods[$method]; + list($function, $algorithm) = self::$supported_algs[$alg]; switch($function) { case 'hash_hmac': - return hash_hmac($algo, $msg, $key, true); + return hash_hmac($algorithm, $msg, $key, true); case 'openssl': $signature = ''; - $success = openssl_sign($msg, $signature, $key, $algo); + $success = openssl_sign($msg, $signature, $key, $algorithm); if (!$success) { throw new DomainException("OpenSSL unable to sign data"); } else { @@ -166,24 +167,20 @@ class JWT * @param string $msg the original message * @param string $signature * @param string|resource $key for HS*, a string key works. for RS*, must be a resource of an openssl public key - * @param string $method + * @param string $algorithms * @return bool * @throws DomainException Invalid Algorithm or OpenSSL failure */ - public static function verify($msg, $signature, $key, $method = 'HS256') + private static function verify($msg, $signature, $key, $alg) { - if (empty(self::$methods[$method])) { + if (empty(self::$supported_algs[$alg])) { throw new DomainException('Algorithm not supported'); } - if (self::$only_method === null) { - throw new DomainException('Algorithm not specified'); - } elseif ($method !== self::$only_method) { - throw new DomainException('Incorrect algorithm error'); - } - list($function, $algo) = self::$methods[$method]; + + list($function, $algorithm) = self::$supported_algs[$alg]; switch($function) { case 'openssl': - $success = openssl_verify($msg, $signature, $key, $algo); + $success = openssl_verify($msg, $signature, $key, $algorithm); if (!$success) { throw new DomainException("OpenSSL unable to verify data: " . openssl_error_string()); } else { @@ -191,7 +188,7 @@ class JWT } case 'hash_hmac': default: - $hash = hash_hmac($algo, $msg, $key, true); + $hash = hash_hmac($algorithm, $msg, $key, true); if (function_exists('hash_equals')) { return hash_equals($signature, $hash); } @@ -309,7 +306,7 @@ class JWT : 'Unknown JSON error: ' . $errno ); } - + /** * Get the number of bytes in cryptographic strings. * @@ -323,22 +320,4 @@ class JWT } return strlen($str); } - - /** - * Set the only allowed method for this server. - * - * @ref https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ - * - * @param string $method array index in self::$methods - * - * @return boolean - */ - public static function setOnlyAllowedMethod($method) - { - if (!empty(self::$methods[$method])) { - self::$only_method = $method; - return true; - } - return false; - } } diff --git a/run-tests.sh b/run-tests.sh index 9d6643e..d37c30f 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -26,6 +26,7 @@ if [ $? -eq 0 ]; then echo echo -e "\033[33mBegin Unit Testing\033[0m" # Run the testing suite + php --version php phpunit.phar --configuration phpunit.xml.dist else echo diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 7b9c102..c7ed6c1 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -102,7 +102,7 @@ class JWTTest extends PHPUnit_Framework_TestCase $privKey = openssl_pkey_new(array('digest_alg' => 'sha256', 'private_key_bits' => 1024, 'private_key_type' => OPENSSL_KEYTYPE_RSA)); - JWT::setOnlyAllowedMethod('RS256'); + //JWT::setOnlyAllowedMethod('RS256'); $msg = JWT::encode('abc', $privKey, 'RS256'); $pubKey = openssl_pkey_get_details($privKey); $pubKey = $pubKey['key']; @@ -113,7 +113,7 @@ class JWTTest extends PHPUnit_Framework_TestCase public function testKIDChooser() { $keys = array('1' => 'my_key', '2' => 'my_key2'); - JWT::setOnlyAllowedMethod('HS256'); + //JWT::setOnlyAllowedMethod('HS256'); $msg = JWT::encode('abc', $keys['1'], 'HS256', '1'); $decoded = JWT::decode($msg, $keys, true); $this->assertEquals($decoded, 'abc'); |