Fixed capitalization, tests
This commit is contained in:
		
							
								
								
									
										30
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| # SimpleJwt | # SimpleJWT | ||||||
|  |  | ||||||
| This is a simple library for generating (signing) and verifying JWT tokens. It | This is a simple library for generating (signing) and verifying JWT tokens. It | ||||||
| is by no means an advanced library. If you just need to sign and refresh tokens | is by no means an advanced library. If you just need to sign and refresh tokens | ||||||
| @@ -27,23 +27,23 @@ Install using composer: | |||||||
|  |  | ||||||
| ## Usage | ## Usage | ||||||
|  |  | ||||||
| You need a key for both generating and parsing tokens. Create a `JwtDerivedKey` | You need a key for both generating and parsing tokens. Create a `JWTDerivedKey` | ||||||
| or a `JwtPlaintextKey` and pass it to the `JwtToken` constructor: | or a `JWTPlaintextKey` and pass it to the `JWTToken` constructor: | ||||||
|  |  | ||||||
|     use NoccyLabs\SimpleJwt\Key\{JwtDerivedKey,JwtPlaintextKey} |     use NoccyLabs\SimpleJWT\Key\{JWTDerivedKey,JWTPlaintextKey} | ||||||
|  |  | ||||||
|     // Derive a key using secret and salt... |     // Derive a key using secret and salt... | ||||||
|     $key = new JwtDerivedKey("secret", "salt"); |     $key = new JWTDerivedKey("secret", "salt"); | ||||||
|     // ...or use a prepared plaintext key |     // ...or use a prepared plaintext key | ||||||
|     $key = new JwtPlaintextKey("This Should Be Binary Data.."); |     $key = new JWTPlaintextKey("This Should Be Binary Data.."); | ||||||
|  |  | ||||||
| ### Generating tokens | ### Generating tokens | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     use NoccyLabs\SimpleJwt\JwtToken; |     use NoccyLabs\SimpleJWT\JWTToken; | ||||||
|  |  | ||||||
|     $tok = new JwtToken($key); |     $tok = new JWTToken($key); | ||||||
|     $tok->setExpiry("1h"); |     $tok->setExpiry("1h"); | ||||||
|     $tok->claims->add("some/claim/MaxItems", 8); |     $tok->claims->add("some/claim/MaxItems", 8); | ||||||
|  |  | ||||||
| @@ -54,11 +54,11 @@ or a `JwtPlaintextKey` and pass it to the `JwtToken` constructor: | |||||||
|  |  | ||||||
| Parsing is done by passing the raw token as the 2nd parameter | Parsing is done by passing the raw token as the 2nd parameter | ||||||
|  |  | ||||||
|     use NoccyLabs\SimpleJwt\JwtToken; |     use NoccyLabs\SimpleJWT\JWTToken; | ||||||
|  |  | ||||||
|     $str = "...received token..."; |     $str = "...received token..."; | ||||||
|  |  | ||||||
|     $tok = new JwtToken($key, $str); |     $tok = new JWTToken($key, $str); | ||||||
|  |  | ||||||
|     if (!$tok->isValid()) { |     if (!$tok->isValid()) { | ||||||
|         // This check works, but using the validator might be better |         // This check works, but using the validator might be better | ||||||
| @@ -75,9 +75,9 @@ Parsing is done by passing the raw token as the 2nd parameter | |||||||
|  |  | ||||||
| ### Validating tokens | ### Validating tokens | ||||||
|  |  | ||||||
|     use NoccyLabs\SimpleJwt\Validator\JwtValidator; |     use NoccyLabs\SimpleJWT\Validator\JWTValidator; | ||||||
|  |  | ||||||
|     $validator = new JwtValidator(); |     $validator = new JWTValidator(); | ||||||
|     // Require that some claim exists |     // Require that some claim exists | ||||||
|     $validator |     $validator | ||||||
|         ->requireIssuer("api.issuer.tld") |         ->requireIssuer("api.issuer.tld") | ||||||
| @@ -85,11 +85,11 @@ Parsing is done by passing the raw token as the 2nd parameter | |||||||
|         ->addRequiredClaim("some/required/Claim"); |         ->addRequiredClaim("some/required/Claim"); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|         // Pass a JwtToken to validateToken()... |         // Pass a JWTToken to validateToken()... | ||||||
|         $valid = $validator->validateToken($tok); |         $valid = $validator->validateToken($tok); | ||||||
|         // ...or pass a JwtKeyInterface and the raw string to validate() |         // ...or pass a JWTKeyInterface and the raw string to validate() | ||||||
|         $valid = $validator->validate($key, $tokenstr); |         $valid = $validator->validate($key, $tokenstr); | ||||||
|     } |     } | ||||||
|     catch (JwtValidatorException $e) { |     catch (JWTValidatorException $e) { | ||||||
|         // validation failed |         // validation failed | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -11,7 +11,15 @@ | |||||||
|     ], |     ], | ||||||
|     "autoload": { |     "autoload": { | ||||||
|         "psr-4": { |         "psr-4": { | ||||||
|             "NoccyLabs\\SimpleJwt\\": "src/" |             "NoccyLabs\\SimpleJWT\\": "src/" | ||||||
|         } |         } | ||||||
|  |     }, | ||||||
|  |     "require": { | ||||||
|  |         "php": "^7.4|^8.0", | ||||||
|  |         "ext-json": "*" | ||||||
|  |     }, | ||||||
|  |     "require-dev": { | ||||||
|  |         "phpunit/phpunit": "^10.0", | ||||||
|  |         "phpstan/phpstan": "^1.10" | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										12
									
								
								phpstan.neon
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								phpstan.neon
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | parameters: | ||||||
|  |   level: 5 | ||||||
|  |      | ||||||
|  |   excludePaths: | ||||||
|  |     - doc | ||||||
|  |     - vendor | ||||||
|  |     - tests | ||||||
|  |  | ||||||
|  |   # Paths to include in the analysis | ||||||
|  |   paths: | ||||||
|  |     - src | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								phpunit.xml
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								phpunit.xml
									
									
									
									
									
								
							| @@ -1,22 +1,13 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" bootstrap="vendor/autoload.php" executionOrder="depends,defects" beStrictAboutOutputDuringTests="true" cacheDirectory=".phpunit.cache" requireCoverageMetadata="true" beStrictAboutCoverageMetadata="true"> | ||||||
|          xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd" |   <coverage> | ||||||
|          bootstrap="vendor/autoload.php" |     <include> | ||||||
|          executionOrder="depends,defects" |       <directory suffix=".php">src</directory> | ||||||
|          forceCoversAnnotation="true" |     </include> | ||||||
|          beStrictAboutCoversAnnotation="true" |   </coverage> | ||||||
|          beStrictAboutOutputDuringTests="true" |  | ||||||
|          beStrictAboutTodoAnnotatedTests="true" |  | ||||||
|          verbose="true"> |  | ||||||
|   <testsuites> |   <testsuites> | ||||||
|     <testsuite name="default"> |     <testsuite name="default"> | ||||||
|       <directory suffix="Test.php">tests</directory> |       <directory suffix="Test.php">tests</directory> | ||||||
|     </testsuite> |     </testsuite> | ||||||
|   </testsuites> |   </testsuites> | ||||||
|  |  | ||||||
|     <filter> |  | ||||||
|         <whitelist processUncoveredFilesFromWhitelist="true"> |  | ||||||
|             <directory suffix=".php">src</directory> |  | ||||||
|         </whitelist> |  | ||||||
|     </filter> |  | ||||||
| </phpunit> | </phpunit> | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Collection; | namespace NoccyLabs\SimpleJWT\Collection; | ||||||
|  |  | ||||||
| use ArrayAccess; | use ArrayAccess; | ||||||
| use Countable; | use Countable; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Collection; | namespace NoccyLabs\SimpleJWT\Collection; | ||||||
|  |  | ||||||
|  |  | ||||||
| class PropertyException extends \RuntimeException | class PropertyException extends \RuntimeException | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace NoccyLabs\SimpleJwt; | namespace NoccyLabs\SimpleJWT; | ||||||
| 
 | 
 | ||||||
| use NoccyLabs\SimpleJwt\Collection\PropertyBag; | use NoccyLabs\SimpleJWT\Collection\PropertyBag; | ||||||
| use NoccyLabs\SimpleJwt\Key\KeyInterface; | use NoccyLabs\SimpleJWT\Key\KeyInterface; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  *  |  *  | ||||||
| @@ -13,7 +13,7 @@ use NoccyLabs\SimpleJwt\Key\KeyInterface; | |||||||
|  * @property-read header PropertyBag |  * @property-read header PropertyBag | ||||||
|  * @property-read claim PropertyBag |  * @property-read claim PropertyBag | ||||||
|  */ |  */ | ||||||
| class JwtToken | class JWTToken | ||||||
| { | { | ||||||
|     /** @var PropertyBag */ |     /** @var PropertyBag */ | ||||||
|     private $header; |     private $header; | ||||||
| @@ -54,13 +54,13 @@ class JwtToken | |||||||
|         $this->generated = false; |         $this->generated = false; | ||||||
| 
 | 
 | ||||||
|         [ $header, $payload, $signature ] = explode(".", trim($token), 3); |         [ $header, $payload, $signature ] = explode(".", trim($token), 3); | ||||||
|         $hash = JwtUtil::encode(hash_hmac("sha256", $header.".".$payload, $this->key->getBinaryKey(), true)); |         $hash = JWTUtil::encode(hash_hmac("sha256", $header.".".$payload, $this->key->getBinaryKey(), true)); | ||||||
|         if ($signature == $hash) { |         if ($signature == $hash) { | ||||||
|             $this->valid = true; |             $this->valid = true; | ||||||
|         } |         } | ||||||
|      |      | ||||||
|         $this->header = new PropertyBag(json_decode(JwtUtil::decode($header), true)); |         $this->header = new PropertyBag(json_decode(JWTUtil::decode($header), true)); | ||||||
|         $this->claims = new PropertyBag(json_decode(JwtUtil::decode($payload), true)); |         $this->claims = new PropertyBag(json_decode(JWTUtil::decode($payload), true)); | ||||||
| 
 | 
 | ||||||
|         if ($this->header->has('exp')) { |         if ($this->header->has('exp')) { | ||||||
|             $exp = intval($this->header->get('exp')); |             $exp = intval($this->header->get('exp')); | ||||||
| @@ -136,9 +136,9 @@ class JwtToken | |||||||
| 
 | 
 | ||||||
|     public function getSignedToken(): string |     public function getSignedToken(): string | ||||||
|     { |     { | ||||||
|         $header = JwtUtil::encode($this->header->getJson()); |         $header = JWTUtil::encode($this->header->getJson()); | ||||||
|         $payload = JwtUtil::encode($this->claims->getJson()); |         $payload = JWTUtil::encode($this->claims->getJson()); | ||||||
|         $hash = JwtUtil::encode(hash_hmac("sha256", $header.".".$payload, $this->key->getBinaryKey(), true)); |         $hash = JWTUtil::encode(hash_hmac("sha256", $header.".".$payload, $this->key->getBinaryKey(), true)); | ||||||
|         return $header.".".$payload.".".$hash; |         return $header.".".$payload.".".$hash; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @@ -1,9 +1,9 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace NoccyLabs\SimpleJwt; | namespace NoccyLabs\SimpleJWT; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class JwtUtil | class JWTUtil | ||||||
| { | { | ||||||
|     public static function encode($data) { |     public static function encode($data) { | ||||||
|         return rtrim(str_replace(['+', '/'], ['-', '_'], base64_encode($data)), "="); |         return rtrim(str_replace(['+', '/'], ['-', '_'], base64_encode($data)), "="); | ||||||
| @@ -1,8 +1,8 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace NoccyLabs\SimpleJwt\Key; | namespace NoccyLabs\SimpleJWT\Key; | ||||||
| 
 | 
 | ||||||
| class JwtDerivedKey implements KeyInterface | class JWTDerivedKey implements KeyInterface | ||||||
| { | { | ||||||
|     private $key; |     private $key; | ||||||
| 
 | 
 | ||||||
| @@ -1,8 +1,8 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace NoccyLabs\SimpleJwt\Key; | namespace NoccyLabs\SimpleJWT\Key; | ||||||
| 
 | 
 | ||||||
| class JwtPlaintextKey implements KeyInterface | class JWTPlaintextKey implements KeyInterface | ||||||
| { | { | ||||||
|     private $key; |     private $key; | ||||||
| 
 | 
 | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Key; | namespace NoccyLabs\SimpleJWT\Key; | ||||||
|  |  | ||||||
| interface KeyInterface | interface KeyInterface | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								src/Validator/JWTClaimException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Validator/JWTClaimException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace NoccyLabs\SimpleJWT\Validator; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class JWTClaimException extends JWTValidatorException | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								src/Validator/JWTHeaderException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Validator/JWTHeaderException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace NoccyLabs\SimpleJWT\Validator; | ||||||
|  |  | ||||||
|  | class JWTHeaderException extends JWTValidatorException | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								src/Validator/JWTTokenException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Validator/JWTTokenException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace NoccyLabs\SimpleJWT\Validator; | ||||||
|  |  | ||||||
|  | class JWTTokenException extends JWTValidatorException | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,11 +1,11 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace NoccyLabs\SimpleJwt\Validator; | namespace NoccyLabs\SimpleJWT\Validator; | ||||||
| 
 | 
 | ||||||
| use NoccyLabs\SimpleJwt\JwtToken; | use NoccyLabs\SimpleJWT\JWTToken; | ||||||
| use NoccyLabs\SimpleJwt\Key\KeyInterface; | use NoccyLabs\SimpleJWT\Key\KeyInterface; | ||||||
| 
 | 
 | ||||||
| class JwtValidator | class JWTValidator | ||||||
| { | { | ||||||
|     private $requireHeaders = []; |     private $requireHeaders = []; | ||||||
| 
 | 
 | ||||||
| @@ -41,32 +41,32 @@ class JwtValidator | |||||||
|         $this->requireAudience = (array)$audience; |         $this->requireAudience = (array)$audience; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function validateToken(JwtToken $token) |     public function validateToken(JWTToken $token) | ||||||
|     { |     { | ||||||
|         if (!$token->isValid()) { |         if (!$token->isValid()) { | ||||||
|             throw new JwtTokenException("The token is not valid"); |             throw new JWTTokenException("The token is not valid"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!$token->header->hasAll($this->requireHeaders)) { |         if (!$token->header->hasAll($this->requireHeaders)) { | ||||||
|             throw new JwtHeaderException("The token is missing one or more required headers"); |             throw new JWTHeaderException("The token is missing one or more required headers"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!$token->claims->hasAll($this->requireClaims)) { |         if (!$token->claims->hasAll($this->requireClaims)) { | ||||||
|             throw new JwtHeaderException("The token is missing one or more required claims"); |             throw new JWTHeaderException("The token is missing one or more required claims"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if ($this->requireIssuer) { |         if ($this->requireIssuer) { | ||||||
|             $hasIssuer = $token->header->has("iss"); |             $hasIssuer = $token->header->has("iss"); | ||||||
|             if ((!$hasIssuer) |             if ((!$hasIssuer) | ||||||
|             || (!in_array($token->header->get("iss"), $this->requireIssuer))) |             || (!in_array($token->header->get("iss"), $this->requireIssuer))) | ||||||
|                 throw new JwtTokenException("Invalid issuer"); |                 throw new JWTTokenException("Invalid issuer"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if ($this->requireAudience) { |         if ($this->requireAudience) { | ||||||
|             $hasAudience = $token->header->has("aud"); |             $hasAudience = $token->header->has("aud"); | ||||||
|             if ((!$hasAudience) |             if ((!$hasAudience) | ||||||
|             || (!in_array($token->header->get("aud"), $this->requireAudience))) |             || (!in_array($token->header->get("aud"), $this->requireAudience))) | ||||||
|                 throw new JwtTokenException("Invalid audience"); |                 throw new JWTTokenException("Invalid audience"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return true; |         return true; | ||||||
| @@ -74,7 +74,7 @@ class JwtValidator | |||||||
| 
 | 
 | ||||||
|     public function validate(KeyInterface $key, string $raw) |     public function validate(KeyInterface $key, string $raw) | ||||||
|     { |     { | ||||||
|         $token = new JwtToken($key, $raw); |         $token = new JWTToken($key, $raw); | ||||||
|         if ($this->validateToken($token)) { |         if ($this->validateToken($token)) { | ||||||
|             return $token; |             return $token; | ||||||
|         } |         } | ||||||
							
								
								
									
										8
									
								
								src/Validator/JWTValidatorException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Validator/JWTValidatorException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace NoccyLabs\SimpleJWT\Validator; | ||||||
|  |  | ||||||
|  | class JWTValidatorException extends \RuntimeException | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,9 +0,0 @@ | |||||||
| <?php |  | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Validator; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class JwtClaimException extends JwtValidatorException |  | ||||||
| { |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,8 +0,0 @@ | |||||||
| <?php |  | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Validator; |  | ||||||
|  |  | ||||||
| class JwtHeaderException extends JwtValidatorException |  | ||||||
| { |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,8 +0,0 @@ | |||||||
| <?php |  | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Validator; |  | ||||||
|  |  | ||||||
| class JwtTokenException extends JwtValidatorException |  | ||||||
| { |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,8 +0,0 @@ | |||||||
| <?php |  | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Validator; |  | ||||||
|  |  | ||||||
| class JwtValidatorException extends \RuntimeException |  | ||||||
| { |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,17 +1,20 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt; | namespace NoccyLabs\SimpleJWT; | ||||||
|  |  | ||||||
| use NoccyLabs\SimpleJwt\Key\JwtPlaintextKey; | use NoccyLabs\SimpleJWT\Key\JWTPlaintextKey; | ||||||
|  |  | ||||||
| class JwtTokenTest extends \PhpUnit\Framework\TestCase | class JWTTokenTest extends \PHPUnit\Framework\TestCase | ||||||
| { | { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testGeneratingTokens() |     public function testGeneratingTokens() | ||||||
|     { |     { | ||||||
|         $key = new JwtPlaintextKey("test"); |         $key = new JWTPlaintextKey("test"); | ||||||
|  |  | ||||||
|         $tok = new JwtToken($key); |         $tok = new JWTToken($key); | ||||||
|         $tok->addClaim("foo", true); |         $tok->addClaim("foo", true); | ||||||
|  |  | ||||||
|         $token = $tok->getSignedToken(); |         $token = $tok->getSignedToken(); | ||||||
| @@ -20,16 +23,19 @@ class JwtTokenTest extends \PhpUnit\Framework\TestCase | |||||||
|         $this->assertTrue($tok->isGenerated()); |         $this->assertTrue($tok->isGenerated()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testParsingTokens() |     public function testParsingTokens() | ||||||
|     { |     { | ||||||
|         $key = new JwtPlaintextKey("test"); |         $key = new JWTPlaintextKey("test"); | ||||||
|  |  | ||||||
|         $tok = new JwtToken($key); |         $tok = new JWTToken($key); | ||||||
|         $tok->addClaim("foo", true); |         $tok->addClaim("foo", true); | ||||||
|  |  | ||||||
|         $token = $tok->getSignedToken(); |         $token = $tok->getSignedToken(); | ||||||
|  |  | ||||||
|         $parsed = new JwtToken($key, $token); |         $parsed = new JWTToken($key, $token); | ||||||
|  |  | ||||||
|         $this->assertTrue($parsed->isValid()); |         $this->assertTrue($parsed->isValid()); | ||||||
|         $this->assertFalse($parsed->isGenerated()); |         $this->assertFalse($parsed->isGenerated()); | ||||||
|   | |||||||
| @@ -1,16 +1,19 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt; | namespace NoccyLabs\SimpleJWT; | ||||||
|  |  | ||||||
|  |  | ||||||
| class JwtUtilTest extends \PhpUnit\Framework\TestCase | class JWTUtilTest extends \PHPUnit\Framework\TestCase | ||||||
| { | { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testTheEncodingShouldBeSymmetric() |     public function testTheEncodingShouldBeSymmetric() | ||||||
|     { |     { | ||||||
|         $v1a = "HelloWorld"; |         $v1a = "HelloWorld"; | ||||||
|         $v1b = JwtUtil::encode($v1a); |         $v1b = JWTUtil::encode($v1a); | ||||||
|         $v1c = JwtUtil::decode($v1b); |         $v1c = JWTUtil::decode($v1b); | ||||||
|  |  | ||||||
|         $this->assertEquals($v1a, $v1c); |         $this->assertEquals($v1a, $v1c); | ||||||
|         $this->assertNotEquals($v1a, $v1b); |         $this->assertNotEquals($v1a, $v1b); | ||||||
|   | |||||||
| @@ -1,34 +1,40 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Key; | namespace NoccyLabs\SimpleJWT\Key; | ||||||
|  |  | ||||||
|  |  | ||||||
| class JwtDerivedKeyTest extends \PhpUnit\Framework\TestCase | class JWTDerivedKeyTest extends \PHPUnit\Framework\TestCase | ||||||
| { | { | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testTheDerivedKeysShouldBeConsistent() |     public function testTheDerivedKeysShouldBeConsistent() | ||||||
|     { |     { | ||||||
|         $key1a = new JwtDerivedKey("foo", "foosalt"); |         $key1a = new JWTDerivedKey("foo", "foosalt"); | ||||||
|         $key1b = new JwtDerivedKey("foo", "foosalt"); |         $key1b = new JWTDerivedKey("foo", "foosalt"); | ||||||
|         $this->assertNotNull($key1a); |         $this->assertNotNull($key1a); | ||||||
|         $this->assertEquals($key1a->getBinaryKey(), $key1b->getBinaryKey()); |         $this->assertEquals($key1a->getBinaryKey(), $key1b->getBinaryKey()); | ||||||
|  |  | ||||||
|         $key2a = new JwtDerivedKey("bar", "foosalt"); |         $key2a = new JWTDerivedKey("bar", "foosalt"); | ||||||
|         $key2b = new JwtDerivedKey("bar", "barsalt"); |         $key2b = new JWTDerivedKey("bar", "barsalt"); | ||||||
|         $key2c = new JwtDerivedKey("bar", "barsalt"); |         $key2c = new JWTDerivedKey("bar", "barsalt"); | ||||||
|         $this->assertNotNull($key2a); |         $this->assertNotNull($key2a); | ||||||
|         $this->assertNotEquals($key2a->getBinaryKey(), $key2b->getBinaryKey()); |         $this->assertNotEquals($key2a->getBinaryKey(), $key2b->getBinaryKey()); | ||||||
|         $this->assertEquals($key2b->getBinaryKey(), $key2c->getBinaryKey()); |         $this->assertEquals($key2b->getBinaryKey(), $key2c->getBinaryKey()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testTheDerivedKeysShouldBeUnique() |     public function testTheDerivedKeysShouldBeUnique() | ||||||
|     { |     { | ||||||
|         $keys = []; |         $keys = []; | ||||||
|         $keys[] = (new JwtDerivedKey("foo", "foosalt"))->getBinaryKey(); |         $keys[] = (new JWTDerivedKey("foo", "foosalt"))->getBinaryKey(); | ||||||
|         $keys[] = (new JwtDerivedKey("foo", "barsalt"))->getBinaryKey(); |         $keys[] = (new JWTDerivedKey("foo", "barsalt"))->getBinaryKey(); | ||||||
|         $keys[] = (new JwtDerivedKey("foo", "bazsalt"))->getBinaryKey(); |         $keys[] = (new JWTDerivedKey("foo", "bazsalt"))->getBinaryKey(); | ||||||
|         $keys[] = (new JwtDerivedKey("bar", "foosalt"))->getBinaryKey(); |         $keys[] = (new JWTDerivedKey("bar", "foosalt"))->getBinaryKey(); | ||||||
|         $keys[] = (new JwtDerivedKey("bar", "barsalt"))->getBinaryKey(); |         $keys[] = (new JWTDerivedKey("bar", "barsalt"))->getBinaryKey(); | ||||||
|         $keys[] = (new JwtDerivedKey("bar", "bazsalt"))->getBinaryKey(); |         $keys[] = (new JWTDerivedKey("bar", "bazsalt"))->getBinaryKey(); | ||||||
|  |  | ||||||
|         $unique = array_unique($keys); |         $unique = array_unique($keys); | ||||||
|         $this->assertEquals(count($keys), count($unique)); |         $this->assertEquals(count($keys), count($unique)); | ||||||
|   | |||||||
| @@ -1,16 +1,19 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Key; | namespace NoccyLabs\SimpleJWT\Key; | ||||||
|  |  | ||||||
|  |  | ||||||
| class JwtPlaintextKeyTest extends \PhpUnit\Framework\TestCase | class JWTPlaintextKeyTest extends \PHPUnit\Framework\TestCase | ||||||
| { | { | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testThePlaintextKeyShouldBeReturned() |     public function testThePlaintextKeyShouldBeReturned() | ||||||
|     { |     { | ||||||
|         $key = new JwtPlaintextKey("foo"); |         $key = new JWTPlaintextKey("foo"); | ||||||
|         $this->assertEquals("foo", $key->getBinaryKey()); |         $this->assertEquals("foo", $key->getBinaryKey()); | ||||||
|  |  | ||||||
|         $key = new JwtPlaintextKey("bar"); |         $key = new JWTPlaintextKey("bar"); | ||||||
|         $this->assertEquals("bar", $key->getBinaryKey()); |         $this->assertEquals("bar", $key->getBinaryKey()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,49 +1,56 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| namespace NoccyLabs\SimpleJwt\Validator; | namespace NoccyLabs\SimpleJWT\Validator; | ||||||
|  |  | ||||||
| use NoccyLabs\SimpleJwt\JwtToken; | use NoccyLabs\SimpleJWT\JWTToken; | ||||||
| use NoccyLabs\SimpleJwt\Key\JwtPlaintextKey; | use NoccyLabs\SimpleJWT\Key\JWTPlaintextKey; | ||||||
|  |  | ||||||
| class JwtValidatorTest extends \PhpUnit\Framework\TestCase | class JWTValidatorTest extends \PHPUnit\Framework\TestCase | ||||||
| { | { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testValidTokensShouldPassWithDefaultConfiguration() |     public function testValidTokensShouldPassWithDefaultConfiguration() | ||||||
|     { |     { | ||||||
|         $key = new JwtPlaintextKey("key"); |         $key = new JWTPlaintextKey("key"); | ||||||
|         $token = new JwtToken($key); |         $token = new JWTToken($key); | ||||||
|          |          | ||||||
|         $validator = new JwtValidator(); |         $validator = new JWTValidator(); | ||||||
|         $valid = $validator->validateToken($token); |         $valid = $validator->validateToken($token); | ||||||
|         $this->assertEquals(true, $valid); |         $this->assertEquals(true, $valid); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @covers  | ||||||
|  |      */ | ||||||
|     public function testExpiredTokensShouldFailWithException() |     public function testExpiredTokensShouldFailWithException() | ||||||
|     { |     { | ||||||
|         $key = new JwtPlaintextKey("key"); |         $key = new JWTPlaintextKey("key"); | ||||||
|         $token = new JwtToken($key); |         $token = new JWTToken($key); | ||||||
|         $token->header->set("exp", 0); |         $token->header->set("exp", 0); | ||||||
|  |  | ||||||
|         $token = new JwtToken($key, $token->getSignedToken());  |         $token = new JWTToken($key, $token->getSignedToken());  | ||||||
|          |          | ||||||
|         $validator = new JwtValidator(); |         $validator = new JWTValidator(); | ||||||
|         $this->expectException(JwtTokenException::class); |         $this->expectException(JWTTokenException::class); | ||||||
|         $valid = $validator->validateToken($token); |         $valid = $validator->validateToken($token); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|  |      * @covers  | ||||||
|      * @dataProvider tokenGenerator |      * @dataProvider tokenGenerator | ||||||
|      */ |      */ | ||||||
|     public function testPinningIssuer($issuer,$audience,$key,$token) |     public function testPinningIssuer($issuer,$audience,$key,$token) | ||||||
|     { |     { | ||||||
|         $goodIssuer = "a-dom.tld"; |         $goodIssuer = "a-dom.tld"; | ||||||
|         $jwtKey = new JwtPlaintextKey($key); |         $jwtKey = new JWTPlaintextKey($key); | ||||||
|         $jwtToken = new JwtToken($jwtKey, $token); |         $jwtToken = new JWTToken($jwtKey, $token); | ||||||
|  |  | ||||||
|         $validator = new JwtValidator(); |         $validator = new JWTValidator(); | ||||||
|         $validator->requireIssuer($goodIssuer); |         $validator->requireIssuer($goodIssuer); | ||||||
|         if ($goodIssuer != $issuer) { |         if ($goodIssuer != $issuer) { | ||||||
|             $this->expectException(JwtTokenException::class); |             $this->expectException(JWTTokenException::class); | ||||||
|         } |         } | ||||||
|         $valid = $validator->validateToken($jwtToken); |         $valid = $validator->validateToken($jwtToken); | ||||||
|         if ($goodIssuer == $issuer) { |         if ($goodIssuer == $issuer) { | ||||||
| @@ -52,18 +59,19 @@ class JwtValidatorTest extends \PhpUnit\Framework\TestCase | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|  |      * @covers  | ||||||
|      * @dataProvider tokenGenerator |      * @dataProvider tokenGenerator | ||||||
|      */ |      */ | ||||||
|     public function testPinningAudience($issuer,$audience,$key,$token) |     public function testPinningAudience($issuer,$audience,$key,$token) | ||||||
|     { |     { | ||||||
|         $goodAudience = [ "a-dom.tld", "app.a-dom.tld" ]; |         $goodAudience = [ "a-dom.tld", "app.a-dom.tld" ]; | ||||||
|         $jwtKey = new JwtPlaintextKey($key); |         $jwtKey = new JWTPlaintextKey($key); | ||||||
|         $jwtToken = new JwtToken($jwtKey, $token); |         $jwtToken = new JWTToken($jwtKey, $token); | ||||||
|  |  | ||||||
|         $validator = new JwtValidator(); |         $validator = new JWTValidator(); | ||||||
|         $validator->requireAudience($goodAudience); |         $validator->requireAudience($goodAudience); | ||||||
|         if (!in_array($audience, $goodAudience)) { |         if (!in_array($audience, $goodAudience)) { | ||||||
|             $this->expectException(JwtTokenException::class); |             $this->expectException(JWTTokenException::class); | ||||||
|         } |         } | ||||||
|         $valid = $validator->validateToken($jwtToken); |         $valid = $validator->validateToken($jwtToken); | ||||||
|         if (in_array($audience, $goodAudience)) { |         if (in_array($audience, $goodAudience)) { | ||||||
| @@ -72,20 +80,21 @@ class JwtValidatorTest extends \PhpUnit\Framework\TestCase | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|  |      * @covers  | ||||||
|      * @dataProvider tokenGenerator |      * @dataProvider tokenGenerator | ||||||
|      */ |      */ | ||||||
|     public function testPinningBoth($issuer,$audience,$key,$token) |     public function testPinningBoth($issuer,$audience,$key,$token) | ||||||
|     { |     { | ||||||
|         $goodIssuer = "a-dom.tld"; |         $goodIssuer = "a-dom.tld"; | ||||||
|         $goodAudience = [ "a-dom.tld", "app.a-dom.tld" ]; |         $goodAudience = [ "a-dom.tld", "app.a-dom.tld" ]; | ||||||
|         $jwtKey = new JwtPlaintextKey($key); |         $jwtKey = new JWTPlaintextKey($key); | ||||||
|         $jwtToken = new JwtToken($jwtKey, $token); |         $jwtToken = new JWTToken($jwtKey, $token); | ||||||
|  |  | ||||||
|         $validator = new JwtValidator(); |         $validator = new JWTValidator(); | ||||||
|         $validator->requireIssuer($goodIssuer); |         $validator->requireIssuer($goodIssuer); | ||||||
|         $validator->requireAudience($goodAudience); |         $validator->requireAudience($goodAudience); | ||||||
|         if (($goodIssuer != $issuer) || (!in_array($audience, $goodAudience))) { |         if (($goodIssuer != $issuer) || (!in_array($audience, $goodAudience))) { | ||||||
|             $this->expectException(JwtTokenException::class); |             $this->expectException(JWTTokenException::class); | ||||||
|         } |         } | ||||||
|         $valid = $validator->validateToken($jwtToken); |         $valid = $validator->validateToken($jwtToken); | ||||||
|         if (($goodIssuer == $issuer) && (in_array($audience, $goodAudience))) { |         if (($goodIssuer == $issuer) && (in_array($audience, $goodAudience))) { | ||||||
| @@ -93,21 +102,21 @@ class JwtValidatorTest extends \PhpUnit\Framework\TestCase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function tokenGenerator() |     public static function tokenGenerator() | ||||||
|     { |     { | ||||||
|         $keyrand = function () { |         $keyrand = function () { | ||||||
|             return substr(sha1(microtime(true).rand(0,65535)), 5, 10); |             return substr(sha1(microtime(true).rand(0,65535)), 5, 10); | ||||||
|         }; |         }; | ||||||
|         $token = function ($head,$claims,$key) { |         $token = function ($head,$claims,$key) { | ||||||
|             $jwtKey = new JwtPlaintextKey($key); |             $jwtKey = new JWTPlaintextKey($key); | ||||||
|             $tok = new JwtToken($jwtKey); |             $tok = new JWTToken($jwtKey); | ||||||
|             $tok->header->setAll($head); |             $tok->header->setAll($head); | ||||||
|             $tok->claims->setAll($claims); |             $tok->claims->setAll($claims); | ||||||
|             return $tok->getSignedToken(); |             return $tok->getSignedToken(); | ||||||
|         }; |         }; | ||||||
|         $row = function ($iss, $aud, array $claims) use ($keyrand, $token) { |         $row = function ($iss, $aud, array $claims) use ($keyrand, $token) { | ||||||
|             $key = $keyrand(); |             $key = $keyrand(); | ||||||
|             $jwtKey = new JwtPlaintextKey($key); |             $jwtKey = new JWTPlaintextKey($key); | ||||||
|             return [ |             return [ | ||||||
|                 $iss, |                 $iss, | ||||||
|                 $aud, |                 $aud, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user