From 91c39c72b22fc3e1191e574089552c1f2041c718 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Wed, 14 Jun 2023 13:26:33 -0600 Subject: [PATCH 1/4] fix: handle invalid http responses (#508) --- src/CachedKeySet.php | 10 ++++++++++ tests/CachedKeySetTest.php | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/CachedKeySet.php b/src/CachedKeySet.php index baf801f1..ee529f9f 100644 --- a/src/CachedKeySet.php +++ b/src/CachedKeySet.php @@ -178,6 +178,16 @@ private function keyIdExists(string $keyId): bool } $request = $this->httpFactory->createRequest('GET', $this->jwksUri); $jwksResponse = $this->httpClient->sendRequest($request); + if ($jwksResponse->getStatusCode() !== 200) { + throw new UnexpectedValueException( + sprintf('HTTP Error: %d %s for URI "%s"', + $jwksResponse->getStatusCode(), + $jwksResponse->getReasonPhrase(), + $this->jwksUri, + ), + $jwksResponse->getStatusCode() + ); + } $this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody()); if (!isset($this->keySet[$keyId])) { diff --git a/tests/CachedKeySetTest.php b/tests/CachedKeySetTest.php index 9142fda6..1e73af6d 100644 --- a/tests/CachedKeySetTest.php +++ b/tests/CachedKeySetTest.php @@ -88,6 +88,37 @@ public function testOutOfBoundsThrowsException() $cachedKeySet['bar']; } + public function testInvalidHttpResponseThrowsException() + { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage('HTTP Error: 404 URL not found'); + $this->expectExceptionCode(404); + + $body = $this->prophesize('Psr\Http\Message\StreamInterface'); + + $response = $this->prophesize('Psr\Http\Message\ResponseInterface'); + $response->getStatusCode() + ->shouldBeCalled() + ->willReturn(404); + $response->getReasonPhrase() + ->shouldBeCalledTimes(1) + ->willReturn('URL not found'); + + $http = $this->prophesize(ClientInterface::class); + $http->sendRequest(Argument::any()) + ->shouldBeCalledTimes(1) + ->willReturn($response->reveal()); + + $cachedKeySet = new CachedKeySet( + $this->testJwksUri, + $http->reveal(), + $this->getMockHttpFactory(), + $this->getMockEmptyCache() + ); + + isset($cachedKeySet[0]); + } + public function testWithExistingKeyId() { $cachedKeySet = new CachedKeySet( @@ -382,6 +413,9 @@ private function getMockHttpClient($testJwks, int $timesCalled = 1) $response->getBody() ->shouldBeCalledTimes($timesCalled) ->willReturn($body->reveal()); + $response->getStatusCode() + ->shouldBeCalledTimes($timesCalled) + ->willReturn(200); $http = $this->prophesize(ClientInterface::class); $http->sendRequest(Argument::any()) From 15d579a76bf2bef1f043c18c9eabbaec0e6989b6 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Wed, 14 Jun 2023 12:28:03 -0700 Subject: [PATCH 2/4] chore(tests): remove unused variable --- tests/CachedKeySetTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/CachedKeySetTest.php b/tests/CachedKeySetTest.php index 1e73af6d..2e4e1f62 100644 --- a/tests/CachedKeySetTest.php +++ b/tests/CachedKeySetTest.php @@ -94,8 +94,6 @@ public function testInvalidHttpResponseThrowsException() $this->expectExceptionMessage('HTTP Error: 404 URL not found'); $this->expectExceptionCode(404); - $body = $this->prophesize('Psr\Http\Message\StreamInterface'); - $response = $this->prophesize('Psr\Http\Message\ResponseInterface'); $response->getStatusCode() ->shouldBeCalled() From 5de4323f4baf4d70bca8663bd87682a69c656c3d Mon Sep 17 00:00:00 2001 From: lleyton Date: Wed, 14 Jun 2023 12:28:31 -0700 Subject: [PATCH 3/4] feat: add support for P-384 curve (#515) --- src/JWK.php | 4 ++-- tests/JWKTest.php | 11 ++++++----- tests/data/ec-jwkset.json | 9 +++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/JWK.php b/src/JWK.php index 873ab41a..63fb2484 100644 --- a/src/JWK.php +++ b/src/JWK.php @@ -27,7 +27,7 @@ class JWK private const EC_CURVES = [ 'P-256' => '1.2.840.10045.3.1.7', // Len: 64 'secp256k1' => '1.3.132.0.10', // Len: 64 - // 'P-384' => '1.3.132.0.34', // Len: 96 (not yet supported) + 'P-384' => '1.3.132.0.34', // Len: 96 // 'P-521' => '1.3.132.0.35', // Len: 132 (not supported) ]; @@ -182,7 +182,7 @@ public static function parseKey(array $jwk, string $defaultAlg = null): ?Key /** * Converts the EC JWK values to pem format. * - * @param string $crv The EC curve (only P-256 is supported) + * @param string $crv The EC curve (only P-256 & P-384 is supported) * @param string $x The EC x-coordinate * @param string $y The EC y-coordinate * diff --git a/tests/JWKTest.php b/tests/JWKTest.php index 4e1b0c67..01082a40 100644 --- a/tests/JWKTest.php +++ b/tests/JWKTest.php @@ -129,11 +129,11 @@ public function testDecodeByJwkKeySetTokenExpired() /** * @dataProvider provideDecodeByJwkKeySet */ - public function testDecodeByJwkKeySet($pemFile, $jwkFile, $alg) + public function testDecodeByJwkKeySet($pemFile, $jwkFile, $alg, $keyId) { $privKey1 = file_get_contents(__DIR__ . '/data/' . $pemFile); $payload = ['sub' => 'foo', 'exp' => strtotime('+10 seconds')]; - $msg = JWT::encode($payload, $privKey1, $alg, 'jwk1'); + $msg = JWT::encode($payload, $privKey1, $alg, $keyId); $jwkSet = json_decode( file_get_contents(__DIR__ . '/data/' . $jwkFile), @@ -149,9 +149,10 @@ public function testDecodeByJwkKeySet($pemFile, $jwkFile, $alg) public function provideDecodeByJwkKeySet() { return [ - ['rsa1-private.pem', 'rsa-jwkset.json', 'RS256'], - ['ecdsa256-private.pem', 'ec-jwkset.json', 'ES256'], - ['ed25519-1.sec', 'ed25519-jwkset.json', 'EdDSA'], + ['rsa1-private.pem', 'rsa-jwkset.json', 'RS256', 'jwk1'], + ['ecdsa256-private.pem', 'ec-jwkset.json', 'ES256', 'jwk1'], + ['ecdsa384-private.pem', 'ec-jwkset.json', 'ES384', 'jwk4'], + ['ed25519-1.sec', 'ed25519-jwkset.json', 'EdDSA', 'jwk1'], ]; } diff --git a/tests/data/ec-jwkset.json b/tests/data/ec-jwkset.json index 213f68ac..50c5b24e 100644 --- a/tests/data/ec-jwkset.json +++ b/tests/data/ec-jwkset.json @@ -26,6 +26,15 @@ "x": "EFpwNuP322bU3WP1DtJgx67L0CUV1MxNixqPVMH2L9Q", "y": "_fSTbijIJjpsqL16cIEvxxf3MaYMY8MbqEq066yV9ls", "alg": "ES256K" + }, + { + "kty": "EC", + "use": "sig", + "crv": "P-384", + "kid": "jwk4", + "x": "FhXXcyKmWkTkdVbWYYU3dtJqpJ0JmLGftEdNzUEFEKSU5MlnLr_FjcneszvXAqEB", + "y": "M4veJF_dO_zhFk44bh_ELXbp0_nn9QaViVtQpuTvpu29eefx6PfUMqX0K--IS4NQ", + "alg": "ES384" } ] } \ No newline at end of file From 48b0210c51718d682e53210c24d25c5a10a2299b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 09:45:35 -0700 Subject: [PATCH 4/4] chore(main): release 6.8.0 (#519) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee78825b..9638f2dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [6.8.0](https://github.com/firebase/php-jwt/compare/v6.7.0...v6.8.0) (2023-06-14) + + +### Features + +* add support for P-384 curve ([#515](https://github.com/firebase/php-jwt/issues/515)) ([5de4323](https://github.com/firebase/php-jwt/commit/5de4323f4baf4d70bca8663bd87682a69c656c3d)) + + +### Bug Fixes + +* handle invalid http responses ([#508](https://github.com/firebase/php-jwt/issues/508)) ([91c39c7](https://github.com/firebase/php-jwt/commit/91c39c72b22fc3e1191e574089552c1f2041c718)) + ## [6.7.0](https://github.com/firebase/php-jwt/compare/v6.6.0...v6.7.0) (2023-06-14)