diff --git a/Resources/doc/1-configuration-reference.md b/Resources/doc/1-configuration-reference.md index 2a9e926d..42f2d7e6 100644 --- a/Resources/doc/1-configuration-reference.md +++ b/Resources/doc/1-configuration-reference.md @@ -16,10 +16,11 @@ lexik_jwt_authentication: public_key: '%kernel.project_dir%/config/jwt/public.pem' # path to the public key OR raw public key, required for verifying tokens pass_phrase: 'yourpassphrase' # required for creating tokens # Additional public keys are used to verify signature of incoming tokens, if the key provided in "public_key" configuration node doesn't verify the token + # Can be paths to public key files OR raw public keys additional_public_keys: - '%kernel.project_dir%/config/jwt/public1.pem' - '%kernel.project_dir%/config/jwt/public2.pem' - - '%kernel.project_dir%/config/jwt/public3.pem' + - '%env(PUBLIC3_KEY_TEXT)%' ``` #### Using HMAC diff --git a/Services/KeyLoader/AbstractKeyLoader.php b/Services/KeyLoader/AbstractKeyLoader.php index 082f0778..d62558b4 100644 --- a/Services/KeyLoader/AbstractKeyLoader.php +++ b/Services/KeyLoader/AbstractKeyLoader.php @@ -47,8 +47,11 @@ public function getAdditionalPublicKeys(): array $contents = []; foreach ($this->additionalPublicKeys as $key) { - if (!$key || !is_file($key) || !is_readable($key)) { - throw new \RuntimeException(sprintf('Additional public key "%s" does not exist or is not readable. Did you correctly set the "lexik_jwt_authentication.additional_public_keys" configuration key?', $key)); + if (!$key) { + continue; + } + if (is_file($key) && !is_readable($key)) { + throw new \RuntimeException(sprintf('Additional public key "%s" is not readable. Did you correctly set the "lexik_jwt_authentication.additional_public_keys" configuration key?', $key)); } $contents[] = is_file($key) ? file_get_contents($key) : $key; diff --git a/Tests/Services/KeyLoader/AbstractTestKeyLoader.php b/Tests/Services/KeyLoader/AbstractTestKeyLoader.php index 15065f9a..9b2b7f27 100644 --- a/Tests/Services/KeyLoader/AbstractTestKeyLoader.php +++ b/Tests/Services/KeyLoader/AbstractTestKeyLoader.php @@ -2,6 +2,7 @@ namespace Lexik\Bundle\JWTAuthenticationBundle\Tests\Services\KeyLoader; +use Lexik\Bundle\JWTAuthenticationBundle\Services\KeyLoader\AbstractKeyLoader; use Lexik\Bundle\JWTAuthenticationBundle\Services\KeyLoader\KeyLoaderInterface; use Lexik\Bundle\JWTAuthenticationBundle\Tests\ForwardCompatTestCaseTrait; use PHPUnit\Framework\TestCase; @@ -34,6 +35,48 @@ public function testLoadKeyFromWrongType() $this->keyLoader->loadKey('wrongType'); } + public function testFalsyAdditionalPublicKeysSkipped() + { + $className = $this->getClassName(); + /** @var AbstractKeyLoader $loader */ + $loader = new $className('private.pem', 'public.pem', 'foobar', [null, false, '']); + $this->assertSame([], $loader->getAdditionalPublicKeys()); + } + + public function testLoadingAdditionalPublicKeysAsStrings() + { + $additionalPublicKeys = ['myKeyText1', 'myKeyText2']; + + $className = $this->getClassName(); + /** @var AbstractKeyLoader $loader */ + $loader = new $className('private.pem', 'public.pem', 'foobar', $additionalPublicKeys); + + $this->assertSame($additionalPublicKeys, $loader->getAdditionalPublicKeys()); + } + + public function testLoadingAdditionalPublicKeysFromFiles() + { + file_put_contents('additional-public-1.pem', 'myKeyTextFromFile1'); + file_put_contents('additional-public-2.pem', 'myKeyTextFromFile2'); + + $className = $this->getClassName(); + /** @var AbstractKeyLoader $loader */ + $loader = new $className('private.pem', 'public.pem', 'foobar', ['additional-public-1.pem', 'additional-public-2.pem']); + + $this->assertSame(['myKeyTextFromFile1', 'myKeyTextFromFile2'], $loader->getAdditionalPublicKeys()); + } + + public function testLoadingAdditionalPublicKeysFromFilesAndAsStrings() + { + file_put_contents('additional-public-1.pem', 'myKeyTextFromFile1'); + + $className = $this->getClassName(); + /** @var AbstractKeyLoader $loader */ + $loader = new $className('private.pem', 'public.pem', 'foobar', ['additional-public-1.pem', 'myKeyText2']); + + $this->assertSame(['myKeyTextFromFile1', 'myKeyText2'], $loader->getAdditionalPublicKeys()); + } + /** * {@inheritdoc} */ @@ -49,15 +92,13 @@ public function doTearDown() */ protected function removeKeysIfExist() { - $privateKey = 'private.pem'; - $publicKey = 'public.pem'; - - if (file_exists($publicKey)) { - unlink($publicKey); - } - - if (file_exists($privateKey)) { - unlink($privateKey); + $keys = ['private.pem', 'public.pem', 'additional-public-1.pem', 'additional-public-2.pem']; + foreach ($keys as $key) { + if (file_exists($key)) { + unlink($key); + } } } + + abstract protected function getClassName(): string; } diff --git a/Tests/Services/KeyLoader/OpenSSLKeyLoaderTest.php b/Tests/Services/KeyLoader/OpenSSLKeyLoaderTest.php index d53a60eb..aae7d9a9 100644 --- a/Tests/Services/KeyLoader/OpenSSLKeyLoaderTest.php +++ b/Tests/Services/KeyLoader/OpenSSLKeyLoaderTest.php @@ -42,4 +42,9 @@ public function testLoadInvalidPrivateKey() $this->keyLoader->loadKey('private'); } + + protected function getClassName(): string + { + return OpenSSLKeyLoader::class; + } } diff --git a/Tests/Services/KeyLoader/RawKeyLoaderTest.php b/Tests/Services/KeyLoader/RawKeyLoaderTest.php index 87fdc8d4..10809b9b 100644 --- a/Tests/Services/KeyLoader/RawKeyLoaderTest.php +++ b/Tests/Services/KeyLoader/RawKeyLoaderTest.php @@ -27,4 +27,9 @@ public function testLoadPrivateKey() { $this->assertSame('private.pem', $this->keyLoader->loadKey('private')); } + + protected function getClassName(): string + { + return RawKeyLoader::class; + } }