Skip to content

Commit 6934142

Browse files
committed
Ensure that JWS does not use algorithm none
1 parent 796e0de commit 6934142

File tree

6 files changed

+78
-32
lines changed

6 files changed

+78
-32
lines changed

src/Federation/EntityStatement.php

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
class EntityStatement extends ParsedJws
1818
{
1919
/**
20-
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
21-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
2220
* @return non-empty-string
21+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
22+
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
2323
*/
2424
public function getIssuer(): string
2525
{
@@ -28,9 +28,9 @@ public function getIssuer(): string
2828

2929

3030
/**
31-
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
32-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
3331
* @return non-empty-string
32+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
33+
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
3434
*/
3535
public function getSubject(): string
3636
{
@@ -76,9 +76,9 @@ public function getJwks(): JwksClaim
7676

7777

7878
/**
79-
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
80-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
8179
* @return non-empty-string
80+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
81+
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
8282
*/
8383
public function getType(): string
8484
{
@@ -93,9 +93,9 @@ public function getType(): string
9393

9494

9595
/**
96-
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
97-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
9896
* @return null|non-empty-string[]
97+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
98+
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
9999
*/
100100
public function getAuthorityHints(): ?array
101101
{
@@ -128,9 +128,9 @@ public function getAuthorityHints(): ?array
128128

129129

130130
/**
131-
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
132-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
133131
* @return null|non-empty-string[]
132+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
133+
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
134134
*/
135135
public function getTrustAnchorHints(): ?array
136136
{
@@ -304,9 +304,9 @@ public function getTrustMarkIssuers(): ?TrustMarkIssuersClaimBag
304304

305305

306306
/**
307-
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
308-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
309307
* @return non-empty-string
308+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
309+
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
310310
*/
311311
public function getKeyId(): string
312312
{
@@ -315,11 +315,11 @@ public function getKeyId(): string
315315

316316

317317
/**
318-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
318+
* @return ?non-empty-string
319319
* @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException
320320
* @throws \SimpleSAML\OpenID\Exceptions\OpenIdException
321321
*
322-
* @return ?non-empty-string
322+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
323323
*/
324324
public function getFederationFetchEndpoint(): ?string
325325
{
@@ -339,11 +339,11 @@ public function getFederationFetchEndpoint(): ?string
339339

340340

341341
/**
342-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
342+
* @return ?non-empty-string
343343
* @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException
344344
* @throws \SimpleSAML\OpenID\Exceptions\OpenIdException
345345
*
346-
* @return ?non-empty-string
346+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
347347
*/
348348
public function getFederationTrustMarkEndpoint(): ?string
349349
{
@@ -363,11 +363,11 @@ public function getFederationTrustMarkEndpoint(): ?string
363363

364364

365365
/**
366-
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
366+
* @return ?non-empty-string
367367
* @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException
368368
* @throws \SimpleSAML\OpenID\Exceptions\OpenIdException
369369
*
370-
* @return ?non-empty-string
370+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
371371
*/
372372
public function getFederationTrustMarkStatusEndpoint(): ?string
373373
{
@@ -386,6 +386,19 @@ public function getFederationTrustMarkStatusEndpoint(): ?string
386386
}
387387

388388

389+
/**
390+
* @return non-empty-string
391+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
392+
* @throws \SimpleSAML\OpenID\Exceptions\OpenId4VciProofException
393+
* @throws \SimpleSAML\OpenID\Exceptions\TrustMarkDelegationException
394+
* @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException
395+
*/
396+
public function getAlgorithm(): string
397+
{
398+
return parent::getAlgorithm() ?? throw new EntityStatementException('No Algorithm header claim found.');
399+
}
400+
401+
389402
/**
390403
* @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
391404
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
@@ -426,6 +439,7 @@ protected function validate(): void
426439
$this->getExpirationTime(...),
427440
$this->getJwks(...),
428441
$this->getType(...),
442+
$this->getAlgorithm(...),
429443
$this->getKeyId(...),
430444
$this->getAuthorityHints(...),
431445
$this->getTrustAnchorHints(...),

src/Jws/ParsedJws.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
namespace SimpleSAML\OpenID\Jws;
66

77
use JsonException;
8+
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
89
use SimpleSAML\OpenID\Codebooks\ClaimsEnum;
910
use SimpleSAML\OpenID\Decorators\DateIntervalDecorator;
11+
use SimpleSAML\OpenID\Exceptions\EntityStatementException;
1012
use SimpleSAML\OpenID\Exceptions\JwsException;
1113
use SimpleSAML\OpenID\Factories\ClaimFactory;
1214
use SimpleSAML\OpenID\Helpers;
@@ -377,8 +379,22 @@ public function getAlgorithm(): ?string
377379
{
378380
$claimKey = ClaimsEnum::Alg->value;
379381

380-
$typ = $this->getHeaderClaim($claimKey);
382+
$alg = $this->getHeaderClaim($claimKey);
381383

382-
return is_null($typ) ? null : $this->helpers->type()->ensureNonEmptyString($typ, $claimKey);
384+
if (is_null($alg)) {
385+
return null;
386+
}
387+
388+
$alg = $this->helpers->type()->ensureNonEmptyString($alg, $claimKey);
389+
390+
$algEnum = SignatureAlgorithmEnum::tryFrom($alg) ?? throw new EntityStatementException(
391+
'Invalid Algorithm header claim.',
392+
);
393+
394+
if ($algEnum->isNone()) {
395+
throw new JwsException('Invalid Algorithm header claim (none).');
396+
}
397+
398+
return $alg;
383399
}
384400
}

src/VerifiableCredentials/OpenId4VciProof.php

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace SimpleSAML\OpenID\VerifiableCredentials;
66

7-
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
87
use SimpleSAML\OpenID\Codebooks\ClaimsEnum;
98
use SimpleSAML\OpenID\Codebooks\JwtTypesEnum;
109
use SimpleSAML\OpenID\Exceptions\OpenId4VciProofException;
@@ -21,17 +20,7 @@ class OpenId4VciProof extends ParsedJws
2120
*/
2221
public function getAlgorithm(): string
2322
{
24-
$alg = parent::getAlgorithm() ?? throw new OpenId4VciProofException('No Algorithm header claim found.');
25-
26-
$algEnum = SignatureAlgorithmEnum::tryFrom($alg) ?? throw new OpenId4VciProofException(
27-
'Invalid Algorithm header claim.',
28-
);
29-
30-
if ($algEnum->isNone()) {
31-
throw new OpenId4VciProofException('Invalid Algorithm header claim (none).');
32-
}
33-
34-
return $alg;
23+
return parent::getAlgorithm() ?? throw new OpenId4VciProofException('No Algorithm header claim found.');
3524
}
3625

3726

tests/src/Federation/EntityStatementTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPUnit\Framework\Attributes\UsesClass;
1111
use PHPUnit\Framework\MockObject\MockObject;
1212
use PHPUnit\Framework\TestCase;
13+
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
1314
use SimpleSAML\OpenID\Decorators\DateIntervalDecorator;
1415
use SimpleSAML\OpenID\Exceptions\JwsException;
1516
use SimpleSAML\OpenID\Factories\ClaimFactory;
@@ -24,6 +25,7 @@
2425

2526
#[CoversClass(EntityStatement::class)]
2627
#[UsesClass(ParsedJws::class)]
28+
#[UsesClass(SignatureAlgorithmEnum::class)]
2729
final class EntityStatementTest extends TestCase
2830
{
2931
protected MockObject $signatureMock;

tests/src/Federation/Factories/EntityStatementFactoryTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#[UsesClass(ParsedJwsFactory::class)]
3030
#[UsesClass(ParsedJws::class)]
3131
#[UsesClass(EntityStatement::class)]
32+
#[UsesClass(SignatureAlgorithmEnum::class)]
3233
final class EntityStatementFactoryTest extends TestCase
3334
{
3435
protected MockObject $signatureMock;

tests/src/Jws/ParsedJwsTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
use Jose\Component\Signature\JWS;
88
use Jose\Component\Signature\Signature;
99
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\Attributes\UsesClass;
1011
use PHPUnit\Framework\MockObject\MockObject;
1112
use PHPUnit\Framework\TestCase;
13+
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
1214
use SimpleSAML\OpenID\Decorators\DateIntervalDecorator;
1315
use SimpleSAML\OpenID\Exceptions\JwsException;
1416
use SimpleSAML\OpenID\Factories\ClaimFactory;
@@ -20,6 +22,7 @@
2022
use SimpleSAML\OpenID\Serializers\JwsSerializerManagerDecorator;
2123

2224
#[CoversClass(ParsedJws::class)]
25+
#[UsesClass(SignatureAlgorithmEnum::class)]
2326
final class ParsedJwsTest extends TestCase
2427
{
2528
protected MockObject $jwsDecoratorMock;
@@ -449,4 +452,25 @@ public function testThrowsIfNotBeforeInTheFuture(): void
449452

450453
$this->sut()->getNotBefore();
451454
}
455+
456+
457+
public function testAlgHeaderCanBeNull(): void
458+
{
459+
unset($this->sampleHeader['alg']);
460+
$this->signatureMock->method('getProtectedHeader')->willReturn($this->sampleHeader);
461+
462+
$this->assertNull($this->sut()->getAlgorithm());
463+
}
464+
465+
466+
public function testAlgHeaderCanNotBeNone(): void
467+
{
468+
$this->sampleHeader['alg'] = 'none';
469+
$this->signatureMock->method('getProtectedHeader')->willReturn($this->sampleHeader);
470+
471+
$this->expectException(JwsException::class);
472+
$this->expectExceptionMessage('none');
473+
474+
$this->sut()->getAlgorithm();
475+
}
452476
}

0 commit comments

Comments
 (0)