Skip to content

Commit

Permalink
Merge pull request #3 from MaPePeR/nokidsinglekeyjwkset
Browse files Browse the repository at this point in the history
Allow JWKSet with single key without kid set.
  • Loading branch information
ADmad authored Jan 12, 2022
2 parents e351c5e + c9860e0 commit 2508626
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 3 deletions.
22 changes: 22 additions & 0 deletions src/JWKSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ public function findKeyByKid(string $kid)

throw new RuntimeException('Unknown key');
}

/**
* @return bool
*/
public function hasDefaultKey() : bool
{
return $this->count() === 1;
}

/**
* @return JWK
* @throws RuntimeException
*/
public function getDefaultKey() : JWK
{
if (!$this->hasDefaultKey()) {
throw new \RuntimeException("No default key");
}
reset($this->keys);

return new JWK(current($this->keys));
}

/**
* @return int
Expand Down
10 changes: 7 additions & 3 deletions src/JWT.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ protected function validateHeader($publicKeyOrSecret, DecodeOptions $options)
throw new RuntimeException('Please specify jwk set in DecodeOptions, because there is kid inside header');
}
} else {
if ($publicKeyOrSecret instanceof JWKSet) {
throw new InvalidJWT('No kid inside header, but $privateKeyOrSecret specified as JWKSet');
if ($publicKeyOrSecret instanceof JWKSet && !$publicKeyOrSecret->hasDefaultKey()) {
throw new InvalidJWT('No kid inside header, but $publicKeyOrSecret specified as JWKSet without default');
}
}
}
Expand Down Expand Up @@ -276,7 +276,11 @@ protected function verifySignature($data, $publicKeyOrSecret, DecodeOptions $opt
}

if ($publicKeyOrSecret instanceof JWKSet) {
$jwk = $publicKeyOrSecret->findKeyByKid($this->headers['kid']);
if (isset($this->headers['kid'])) {
$jwk = $publicKeyOrSecret->findKeyByKid($this->headers['kid']);
} else {
$jwk = $publicKeyOrSecret->getDefaultKey();
}
$secretOrKey = $jwk->getPublicKey();
} else {
$secretOrKey = $publicKeyOrSecret;
Expand Down
51 changes: 51 additions & 0 deletions tests/JWKSetTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/**
* SocialConnect project
*/

namespace Test\JWX;

use DateTime;
use SocialConnect\JWX\DecodeOptions;
use SocialConnect\JWX\EncodeOptions;
use SocialConnect\JWX\Exception\ExpiredJWT;
use SocialConnect\JWX\Exception\InvalidJWT;
use SocialConnect\JWX\JWK;
use SocialConnect\JWX\JWKSet;
use SocialConnect\JWX\JWT;

class JWKSetTest extends AbstractTestCase {

public function testDefaultKeyNoKeys() {
$set = new JWKSet(['keys' => []]);

parent::assertFalse($set->hasDefaultKey());

parent::expectException("RuntimeException");
$set->getDefaultKey();
}

public function testDefaultKeyMultipleKeys() {
$set = new JWKSet(['keys' => [
JWK::fromRSAPublicKeyFile(__DIR__ . '/assets/rs256.key.pub')->toArray(),
JWK::fromRSAPublicKeyFile(__DIR__ . '/assets/rs384.key.pub')->toArray(),

]]);

parent::assertFalse($set->hasDefaultKey());

parent::expectException("RuntimeException");
$set->getDefaultKey();
}

public function testDefaultKeySingle() {
$set = new JWKSet(['keys' => [
JWK::fromRSAPublicKeyFile(__DIR__ . '/assets/rs256.key.pub')->toArray(),

]]);

parent::assertTrue($set->hasDefaultKey());

parent::assertInstanceOf(JWK::class, $set->getDefaultKey());
}
}
23 changes: 23 additions & 0 deletions tests/JWTTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,29 @@ public function testValidateHeaderNoKid()
new DecodeOptions(['RS256'])
);
}

public function testValidateHeaderNoKidSingleKey()
{
$kset = new JWKSet(['keys' => [
JWK::fromRSAPublicKeyFile(__DIR__ . '/assets/rs512.key.pub')->toArray(),
]]);

$token = new JWT(
[],
[
'alg' => 'RS256'
]
);

self::callProtectedMethod(
$token,
'validateHeader',
$kset,
new DecodeOptions(['RS256'])
);

parent::assertTrue(true);
}

public function testDecodeWrongNumberOfSegments()
{
Expand Down

0 comments on commit 2508626

Please sign in to comment.