From 859fc8d8f89cd75e3c95d43facee338cc2849d93 Mon Sep 17 00:00:00 2001 From: Andrej Rypo Date: Wed, 19 Apr 2023 16:42:27 +0200 Subject: [PATCH] Mitigation of security issue CVE-2021-46743 --- .github/workflows/php-test.yml | 2 +- changelog.md | 17 +++++ composer.json | 4 +- src/Factory/AuthFactory.php | 20 ------ src/Factory/AuthWizard.php | 25 ++++--- src/FirebaseJwtDecoder.php | 106 +++++------------------------- src/Secret.php | 5 +- src/SecretContract.php | 2 +- tests/FactoryTest.phpt | 7 +- tests/FirebaseJwtDecoderTest.phpt | 105 ++++++++++++++++++++++++----- tests/NoLibTest.phpt | 33 +++++++++- tests/TokenMwTest.phpt | 21 +++--- tests/bootstrap.php | 3 - 13 files changed, 187 insertions(+), 163 deletions(-) diff --git a/.github/workflows/php-test.yml b/.github/workflows/php-test.yml index f05c814..cd863ee 100644 --- a/.github/workflows/php-test.yml +++ b/.github/workflows/php-test.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: include: - - php: '7.4' + - php: '8.0' composer-flags: '--prefer-lowest' - php: '8.0' - php: '8.1' diff --git a/changelog.md b/changelog.md index aa11229..37d5213 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,23 @@ Auth-middleware follows semantic versioning.\ Any issues should be reported. +## v2.0 + +This update reflects security vulnerability patch for **CVE-2021-46743** from `firebase/php-jwt` package in version 5.5 and 6. +As a result, the interface of `FirebaseJwtDecoder` and certain `AuthWizard` methods that create the decoder have been changed. + +- [BC break] dropped PHP 7 support; PHP 8 is now required +- [BC break] removed `AuthFactory::defaultDecoderFactory`, please use `fn() => AuthWizard::defaultDecoder( new Secret($secret,$algo) )` instead +- [BC break] changed the constructor of `FirebaseJwtDecoder` to only accept `SecretContract` implementations +- [BC break] using `AuthWizard::defaultDecoder`, `AuthWizard::decodeTokens()` and `AuthWizard::factory()->decodeTokens()` with `string` `$secret` argument will now only decode tokens using the single default `HS256` algorithm + - previously the same calls resulted in use of any one of the three `HS256`, `HS512`, `HS384` algorithms (the attack vector) + - to mitigate the issue, use an array of key-algo pairs (`Secret[]`) along with `kid` header parameter (see [section 4.5 of RFC 7517](https://www.ietf.org/rfc/rfc7517.txt)) +- the default `FirebaseJwtDecoder` now only works with `firebase/php-jwt` versions 5.5 and 6+ (`5.5.* - 6.*`) +- added `AuthWizard::defaultDecoder` method that directly returns an instance of the `FirebaseJwtDecoder` decoder + +> For more details, see [this issue](https://github.com/firebase/php-jwt/issues/351) or [release notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0). + + ## v1.2 Provides means for mitigation of security vulnerability **CVE-2021-46743** by using the new `Secret` configuration object. diff --git a/composer.json b/composer.json index dfff5b8..975adc8 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": "^7.4 || ^8.0", + "php": "^8.0", "dakujem/generic-middleware": "^1", "psr/http-factory": "^1.0", "psr/http-server-middleware": "^1.0", @@ -18,7 +18,7 @@ }, "require-dev": { "ext-json": "*", - "firebase/php-jwt": "^5", + "firebase/php-jwt": "^6.0|^5.5", "nette/tester": "^2.4.1", "slim/psr7": "^1.2", "slim/slim": "^4.5", diff --git a/src/Factory/AuthFactory.php b/src/Factory/AuthFactory.php index 702b95d..35d28d0 100644 --- a/src/Factory/AuthFactory.php +++ b/src/Factory/AuthFactory.php @@ -4,9 +4,7 @@ namespace Dakujem\Middleware\Factory; -use Dakujem\Middleware\FirebaseJwtDecoder; use Dakujem\Middleware\GenericMiddleware; -use Dakujem\Middleware\SecretContract; use Dakujem\Middleware\TokenManipulators as Man; use Dakujem\Middleware\TokenMiddleware; use LogicException; @@ -165,22 +163,4 @@ public function inspectTokens( ); }); } - - /** - * @deprecated please use AuthWizard::defaultDecoder instead - * - * Creates a default decoder factory. - * The factory can be used for the constructor. - * - * @param string|SecretContract[]|SecretContract $secret secret key for JWT decoder - * @param string|null $algo optional algorithm; only used when $secret is a string - * @return callable fn():FirebaseJwtDecoder - */ - public static function defaultDecoderFactory( - $secret, - ?string $algo = null - ): callable { - $decoder = AuthWizard::defaultDecoder($secret, $algo); - return fn(): FirebaseJwtDecoder => $decoder; - } } diff --git a/src/Factory/AuthWizard.php b/src/Factory/AuthWizard.php index 0e2cab8..d42f716 100644 --- a/src/Factory/AuthWizard.php +++ b/src/Factory/AuthWizard.php @@ -37,12 +37,12 @@ final class AuthWizard * @return TokenMiddleware */ public static function decodeTokens( - $secret, + string|array|SecretContract $secret, ?string $tokenAttribute = null, ?string $headerName = Man::HEADER_NAME, ?string $cookieName = Man::COOKIE_NAME, ?string $errorAttribute = null, - ?Logger $logger = null + ?Logger $logger = null, ): MiddlewareInterface { return self::factory($secret, null)->decodeTokens( $tokenAttribute, @@ -64,7 +64,7 @@ public static function decodeTokens( public static function assertTokens( ResponseFactory $responseFactory, ?string $tokenAttribute = null, - ?string $errorAttribute = null + ?string $errorAttribute = null, ): MiddlewareInterface { return self::factory(null, $responseFactory)->assertTokens($tokenAttribute, $errorAttribute); } @@ -82,7 +82,7 @@ public static function inspectTokens( ResponseFactory $responseFactory, callable $inspector, ?string $tokenAttribute = null, - ?string $errorAttribute = null + ?string $errorAttribute = null, ): MiddlewareInterface { return self::factory(null, $responseFactory)->inspectTokens($inspector, $tokenAttribute, $errorAttribute); } @@ -95,8 +95,8 @@ public static function inspectTokens( * @return AuthFactory */ public static function factory( - $secret, - ?ResponseFactory $responseFactory + string|array|SecretContract|null $secret, + ?ResponseFactory $responseFactory, ): AuthFactory { $decoder = $secret !== null ? self::defaultDecoder($secret) : null; return new AuthFactory( @@ -115,21 +115,20 @@ public static function factory( * @throws */ public static function defaultDecoder( - $secret, - ?string $algo = null + string|array|SecretContract $secret, + ?string $algo = null, ): callable { if (!class_exists(JWT::class)) { throw new LogicException( 'Firebase JWT is not installed. ' . - 'Requires firebase/php-jwt package (`composer require firebase/php-jwt:"^5.5"`).' + 'Requires firebase/php-jwt package (`composer require firebase/php-jwt:"^6.0|^5.5"`).' ); } - if ($algo !== null && is_string($secret)) { - $secret = new Secret($secret, $algo); + if (is_string($secret)) { + $secret = new Secret($secret, $algo ?? self::$defaultAlgo); } return new FirebaseJwtDecoder( - $secret, - $algo, + ...(is_iterable($secret) ? $secret : [$secret]) ); } } diff --git a/src/FirebaseJwtDecoder.php b/src/FirebaseJwtDecoder.php index 401a40a..a01557e 100644 --- a/src/FirebaseJwtDecoder.php +++ b/src/FirebaseJwtDecoder.php @@ -8,29 +8,23 @@ use Firebase\JWT\JWT; use Firebase\JWT\Key; use InvalidArgumentException; +use LogicException; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; -use ReflectionClass; -use ReflectionException; use UnexpectedValueException; /** * A callable decoder that uses Firebase JWT implementation. * - * Notes: - * firebase/php-jwt is a peer dependency, you need to install it separately: - * `composer require firebase/php-jwt:"^5.5"` - * This decoder works with all v5.* branches of firebase/php-jwt, - * but we recommend using version "^5.5" to mitigate a possible security issue CVE-2021-46743. - * - * Alternatively, update dakujem/auth-middleware to v2 and firebase/php-jwt to v6 to prevent the issue completely: - * `composer require dakujem/auth-middleware:"^2" firebase/php-jwt:"^6.0"` + * Note: + * firebase/php-jwt is a peer dependency, it needs to be installed separately: + * `composer require firebase/php-jwt:"^6.0 | ^5.5"` * * Usage with TokenMiddleware: - * $mw = new TokenMiddleware(new FirebaseJwtDecoder(new Secret('my-secret-is-not-committed-to-the-repo'))); + * $mw = new TokenMiddleware(new FirebaseJwtDecoder(new Secret('my-secret-is-not-committed-to-the-repo', 'HS256'))); * * Warning: - * This decoder _only_ ensures that the token has been signed by the given secret key + * This decoder ensures _only_ that the token has been signed by the given secret key * and that it is not expired (`exp` claim) or used before intended (`nbf` and `iat` claims). * The rest of the authorization process is entirely up to your app's logic. * @@ -38,86 +32,23 @@ */ final class FirebaseJwtDecoder { - /** @var Key|Key[]|string */ - private $secret; - private ?array $algos; + /** @var Key|Key[] */ + private Key|array $keys; - public function __construct($secret, ?array $algos = null) + public function __construct(SecretContract ...$secret) { - if (empty($secret)) { - throw new InvalidArgumentException('Invalid configuration: The secret key may not be empty.'); + if (!class_exists(Key::class)) { + throw new LogicException('Peer dependency version mismatch. Please upgrade the `firebase/php-jwt` package.'); } - $algos ??= ['HS256', 'HS512', 'HS384']; - - if (count($algos) === 0) { - throw new InvalidArgumentException('Invalid configuration: No encryption algorithms provided.'); + if (count($secret) === 0) { + throw new InvalidArgumentException('No keys passed to the decoder.'); } - - if (!is_string($secret) && !class_exists(Key::class)) { - throw new UnexpectedValueException( - 'Unsupported configuration. To use the `Secret` objects, upgrade peer library `firebase/php-jwt` to version 5.5 or 6 and above.' - ); - } - if (!is_string($secret)) { - $key = fn(SecretContract $s): Key => new Key($s->keyMaterial(), $s->algorithm()); - if (is_array($secret) && count($secret) === 1) { - $secret = array_pop($secret); - } - if ($secret instanceof SecretContract) { - $this->secret = $key($secret); - } elseif (is_array($secret)) { - $this->secret = array_map($key, $secret); - } else { - throw new UnexpectedValueException( - 'Invalid configuration: The secret must ether be a string, a `SecretContract` object or an array of such objects.' - ); - } + $key = fn(SecretContract $s): Key => new Key($s->keyMaterial(), $s->algorithm()); + if (count($secret) === 1) { + $this->keys = $key(array_pop($secret)); } else { - $this->secret = $secret; - } - - // In certain configurations, the decoding will fail. To prevent the failure, we throw an exception here. - if (is_string($secret) && class_exists(Key::class)) { - if (count($algos) > 1) { - try { - // The following detects v6 of firebase/php-jwt lib. - if ((new ReflectionClass(JWT::class))->getMethod('decode')->getNumberOfParameters() < 3) { - // - // If this is happening to you, there are 3 options: - // 1. use a single secret+algorithm combination either using the `Secret` object or passing an array with a single algorithm to the `$algos` parameter - // 2. use multiple `Secret` objects and pass them to the `$secret` parameter AND use "kid" JWT header parameter when encoding the JWT - // 3. downgrade firebase/php-jwt to version v5.5 or below (not recommended) - // - // This is done to mitigate a possible security issue CVE-2021-46743. - // For more details, see https://github.com/firebase/php-jwt/issues/351. - // - throw new UnexpectedValueException( - 'Peer library `firebase/php-jwt` has been updated to version v6 or above, which does not work with the current secret+algorithm configuration combination. Refer to the documentation od dakujem/auth-middleware for this version to solve the configuration issue.' - ); - } - } catch (ReflectionException $e) { - // ignore - } - // - // If this is happening to you, there are 3 options: - // 1. use a single secret+algorithm combination either using the `Secret` object or passing an array with a single algorithm to the `$algos` parameter - // 2. use multiple `Secret` objects and pass them to the `$secret` parameter AND use "kid" JWT header parameter when encoding the JWT - // 3. ignore this warning or downgrade dakujem/auth-middleware (not recommended) - // - // This is done to mitigate a possible security issue CVE-2021-46743. - // For more details, see https://github.com/firebase/php-jwt/issues/351. - // - trigger_error( - 'Peer library `firebase/php-jwt` has been updated to a version able to circumvent security vulnerability CVE-2021-46743. Please use the `Secret` objects instead of string constants: `new FirebaseJwtDecoder(new Secret($secretString, $algorithm))`.', - E_USER_WARNING, - ); - } - if (count($algos) === 1) { - $algorithm = array_pop($algos); - $this->secret = new Key($secret, $algorithm); - } + $this->keys = array_map($key, $secret); } - $this->algos = $algos; } /** @@ -134,8 +65,7 @@ public function __invoke(string $token, ?LoggerInterface $logger = null): object try { return JWT::decode( $token, - $this->secret, - $this->algos + $this->keys, ); } catch (UnexpectedValueException $throwable) { $logger && $logger->log(LogLevel::DEBUG, $throwable->getMessage(), [$token, $throwable]); diff --git a/src/Secret.php b/src/Secret.php index f8bf020..aa110b9 100644 --- a/src/Secret.php +++ b/src/Secret.php @@ -14,10 +14,9 @@ final class Secret implements SecretContract { private string $algorithm; - private $keyMaterial; - public function __construct($keyMaterial, string $algorithm) + public function __construct(mixed $keyMaterial, string $algorithm) { if (empty($keyMaterial)) { throw new InvalidArgumentException('Type error: $keyMaterial must not be empty'); @@ -29,7 +28,7 @@ public function __construct($keyMaterial, string $algorithm) /** * Return the key material - the secret. */ - public function keyMaterial() + public function keyMaterial(): mixed { return $this->keyMaterial; } diff --git a/src/SecretContract.php b/src/SecretContract.php index adcf1ac..98cabd1 100644 --- a/src/SecretContract.php +++ b/src/SecretContract.php @@ -14,7 +14,7 @@ interface SecretContract /** * Return the key material - the secret. */ - public function keyMaterial(); + public function keyMaterial(): mixed; /** * Return the algorithm valid for this key. diff --git a/tests/FactoryTest.phpt b/tests/FactoryTest.phpt index 2b9b250..44a7a74 100644 --- a/tests/FactoryTest.phpt +++ b/tests/FactoryTest.phpt @@ -25,9 +25,14 @@ use Tester\TestCase; */ class _FactoryTest extends TestCase { + public function testWizardDefaultAlgo() + { + Assert::same('HS256', AuthWizard::$defaultAlgo); + } + public function testAuthFactoryReturnsCorrectMiddleware() { - $f = new AuthFactory(AuthFactory::defaultDecoderFactory('whatever'), new ResponseFactory()); + $f = new AuthFactory(fn() => fn() => null, new ResponseFactory()); Assert::type(TokenMiddleware::class, $f->decodeTokens()); Assert::type(GenericMiddleware::class, $f->assertTokens()); Assert::type(GenericMiddleware::class, $f->inspectTokens(fn() => null)); diff --git a/tests/FirebaseJwtDecoderTest.phpt b/tests/FirebaseJwtDecoderTest.phpt index 90e51fb..750bbea 100644 --- a/tests/FirebaseJwtDecoderTest.phpt +++ b/tests/FirebaseJwtDecoderTest.phpt @@ -7,8 +7,12 @@ namespace Dakujem\Middleware\Test; require_once __DIR__ . '/bootstrap.php'; require_once __DIR__ . '/support/ProxyLogger.php'; +use Dakujem\Middleware\Factory\AuthWizard; use Dakujem\Middleware\FirebaseJwtDecoder; +use Dakujem\Middleware\Secret; +use Dakujem\Middleware\SecretContract; use Dakujem\Middleware\Test\Support\_ProxyLogger; +use Firebase\JWT\JWT; use InvalidArgumentException; use LogicException; use Psr\Log\LogLevel; @@ -27,7 +31,12 @@ use UnexpectedValueException; */ class _FirebaseJwtDecoderTest extends TestCase { - private string $key = 'Dakujem za halusky!'; + private SecretContract $key; + + public function __construct() + { + $this->key = new Secret('Dakujem za halusky!', AuthWizard::$defaultAlgo); + } public function testValidToken() { @@ -38,7 +47,52 @@ class _FirebaseJwtDecoderTest extends TestCase "iat": 1516239022 }'); Assert::equal($expected, (new FirebaseJwtDecoder($this->key))($token)); - Assert::equal($expected, (new FirebaseJwtDecoder($this->key, ['HS256']))($token)); + Assert::equal($expected, (new FirebaseJwtDecoder($this->key))($token)); + } + + public function testMultiKeySupport() + { + $claims = [ + 'sub' => 42, + 'foo' => 'bar', + ]; + $expected = (object)$claims; + + // Test the ability for numeric "kid" (key ID). + $token = JWT::encode($claims, $this->key->keyMaterial(), $this->key->algorithm(), '1'); + $decoder = (new FirebaseJwtDecoder(new Secret('Dakujem za halusky!', 'HS512'), $this->key)); + Assert::equal($expected, $decoder($token)); + + // Test the ability for arbitrary alphanumeric "kid" (key ID). + $token = JWT::encode($claims, $this->key->keyMaterial(), $this->key->algorithm(), 'foo'); + $decoder = (new FirebaseJwtDecoder(bar: new Secret('Dakujem za halusky!', 'HS512'), foo: $this->key)); + Assert::equal($expected, $decoder($token)); + $decoder = (new FirebaseJwtDecoder(bar: new Secret('Dakujem za halusky!', 'HS512'), FOX: $this->key)); + Assert::throws( + fn() => $decoder($token), + UnexpectedValueException::class + ); + $decoder = (new FirebaseJwtDecoder(whatever: $this->key)); // when there is only a single key, the "kid" doesn't matter, only the algo must match + Assert::equal($expected, $decoder($token)); + } + + public function testInvalidSecrets() + { + Assert::type(SecretContract::class, new Secret('foo', '')); + Assert::type(SecretContract::class, new Secret('foo', 'foo')); + + Assert::throws( + fn() => new Secret('', 'foo'), + InvalidArgumentException::class + ); + Assert::throws( + fn() => new Secret(null, 'foo'), + InvalidArgumentException::class + ); + Assert::throws( + fn() => new Secret([], 'foo'), + InvalidArgumentException::class + ); } public function testMalformedToken() @@ -90,13 +144,21 @@ class _FirebaseJwtDecoderTest extends TestCase public function testInvalidKey() { Assert::throws( - fn() => new FirebaseJwtDecoder(''), + fn() => new FirebaseJwtDecoder(), + InvalidArgumentException::class + ); + Assert::throws( + fn() => new Secret([], ''), + InvalidArgumentException::class + ); + Assert::throws( + fn() => new Secret('', 'whatever'), InvalidArgumentException::class ); $token = implode('.', $this->tokenParts()); Assert::throws( - fn() => (new FirebaseJwtDecoder('foobar!'))($token), + fn() => (new FirebaseJwtDecoder(new Secret('foobar!', AuthWizard::$defaultAlgo)))($token), UnexpectedValueException::class ); } @@ -105,11 +167,11 @@ class _FirebaseJwtDecoderTest extends TestCase { $token = implode('.', $this->tokenParts()); Assert::throws( - fn() => (new FirebaseJwtDecoder($this->key, ['ritpalova']))($token), + fn() => (new FirebaseJwtDecoder(new Secret($this->key->keyMaterial(), 'ritpalova')))($token), UnexpectedValueException::class ); Assert::throws( - fn() => (new FirebaseJwtDecoder($this->key, ['HS512', 'HS384']))($token), + fn() => (new FirebaseJwtDecoder(new Secret($this->key->keyMaterial(), 'HS512')))($token), UnexpectedValueException::class ); } @@ -152,17 +214,28 @@ class _FirebaseJwtDecoderTest extends TestCase ); // log on error + $logger = new _ProxyLogger(function ($level, $message, $context) { + Assert::same(LogLevel::DEBUG, $level); + Assert::true($message !== ''); + Assert::same('bad token', $context[0] ?? null); + Assert::type(UnexpectedValueException::class, $context[1] ?? null); + }); + Assert::throws( + function () use ($logger) { + return (new FirebaseJwtDecoder(new Secret($this->key->keyMaterial(), 'foo')))( + 'bad token', + $logger, + ); + }, + UnexpectedValueException::class + ); Assert::throws( - fn() => (new FirebaseJwtDecoder('invalid'))('bad token', new _ProxyLogger(function ( - $level, - $message, - $context - ) { - Assert::same(LogLevel::DEBUG, $level); - Assert::true($message !== ''); - Assert::same('bad token', $context[0] ?? null); - Assert::type(UnexpectedValueException::class, $context[1] ?? null); - })), + function () use ($logger) { + return (new FirebaseJwtDecoder(new Secret('invalid', $this->key->algorithm())))( + 'bad token', + $logger, + ); + }, UnexpectedValueException::class ); } diff --git a/tests/NoLibTest.phpt b/tests/NoLibTest.phpt index 5f63459..e5c232a 100644 --- a/tests/NoLibTest.phpt +++ b/tests/NoLibTest.phpt @@ -7,12 +7,17 @@ namespace Dakujem\Middleware\Test; require_once __DIR__ . '/../vendor/nette/tester/src/bootstrap.php'; require_once __DIR__ . '/../src/Factory/AuthFactory.php'; require_once __DIR__ . '/../src/Factory/AuthWizard.php'; +require_once __DIR__ . '/../src/SecretContract.php'; +require_once __DIR__ . '/../src/Secret.php'; +require_once __DIR__ . '/../src/FirebaseJwtDecoder.php'; require_once __DIR__ . '/../vendor/psr/http-factory/src/ResponseFactoryInterface.php'; require_once __DIR__ . '/../vendor/slim/psr7/src/Factory/ResponseFactory.php'; -use Dakujem\Middleware\Factory\AuthFactory; +use Dakujem\Middleware\Factory\AuthWizard; use Dakujem\Middleware\FirebaseJwtDecoder; +use Dakujem\Middleware\Secret; use LogicException; +use Slim\Psr7\Factory\ResponseFactory; use Tester\Assert; /** @@ -24,7 +29,29 @@ use Tester\Assert; */ Assert::throws( - fn() => AuthFactory::defaultDecoderFactory('doesntmatter'), + fn() => AuthWizard::defaultDecoder('doesntmatter'), LogicException::class, - 'Firebase JWT is not installed. Requires firebase/php-jwt package (`composer require firebase/php-jwt:"^5.5"`).' + 'Firebase JWT is not installed. Requires firebase/php-jwt package (`composer require firebase/php-jwt:"^6.0|^5.5"`).' +); + +// +// Implementation note: +// +// There is an intentional call to `AuthWizard::defaultDecoder` inside `AuthWizard::factory` method +// that creates the decoder callable instance _before_ creating the factory wrapper (fn()=>$decoder). +// Do NOT optimize it into `$secret !== null ? fn() => self::defaultDecoder($secret) : null`. +// +// It is done so that the factory throws instantly and the error is easier to tackle. +// +Assert::throws( + fn() => AuthWizard::factory('doesntmatter', new ResponseFactory()), + LogicException::class, + 'Firebase JWT is not installed. Requires firebase/php-jwt package (`composer require firebase/php-jwt:"^6.0|^5.5"`).' +); + + +Assert::throws( + fn() => new FirebaseJwtDecoder(new Secret('doesntmatter', 'whatever')), + LogicException::class, + 'Peer dependency version mismatch. Please upgrade the `firebase/php-jwt` package.' ); diff --git a/tests/TokenMwTest.phpt b/tests/TokenMwTest.phpt index 49c023d..a12668f 100644 --- a/tests/TokenMwTest.phpt +++ b/tests/TokenMwTest.phpt @@ -10,6 +10,8 @@ require_once __DIR__ . '/support/ProxyLogger.php'; use ArrayIterator; use Dakujem\Middleware\Factory\AuthWizard; use Dakujem\Middleware\FirebaseJwtDecoder; +use Dakujem\Middleware\Secret; +use Dakujem\Middleware\SecretContract; use Dakujem\Middleware\Test\Support\_ProxyLogger; use Dakujem\Middleware\TokenManipulators; use Dakujem\Middleware\TokenMiddleware; @@ -35,24 +37,19 @@ use TypeError; */ class _TokenMwTest extends TestCase { - private string $key = 'Dakujem za halusky!'; - -// protected function setUp() -// { -// parent::setUp(); -// } -// -// protected function tearDown() -// { -// parent::tearDown(); -// } + private SecretContract $key; + + public function __construct() + { + $this->key = new Secret('Dakujem za halusky!', AuthWizard::$defaultAlgo); + } private function validToken(): string { return JWT::encode([ 'sub' => 42, 'foo' => 'bar', - ], $this->key, AuthWizard::$defaultAlgo); + ], $this->key->keyMaterial(), $this->key->algorithm()); } public function testHappyPath() diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 828a616..a8f0fd8 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -15,6 +15,3 @@ // Nette Tester initialization. Environment::setup(); - -// This is done in this version only. See FirebaseJwtDecoder for info. -error_reporting(E_ALL ^ E_USER_WARNING);