Skip to content

Commit 3c590d4

Browse files
committed
Introduce IdTokenFactory
1 parent 9b2219a commit 3c590d4

3 files changed

Lines changed: 237 additions & 0 deletions

File tree

src/Core.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmBag;
1111
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
1212
use SimpleSAML\OpenID\Core\Factories\ClientAssertionFactory;
13+
use SimpleSAML\OpenID\Core\Factories\IdTokenFactory;
1314
use SimpleSAML\OpenID\Core\Factories\RequestObjectFactory;
1415
use SimpleSAML\OpenID\Decorators\DateIntervalDecorator;
1516
use SimpleSAML\OpenID\Factories\AlgorithmManagerDecoratorFactory;
@@ -37,6 +38,8 @@ class Core
3738

3839
protected ?ClientAssertionFactory $clientAssertionFactory = null;
3940

41+
protected ?IdTokenFactory $idTokenFactory = null;
42+
4043
protected ?Helpers $helpers = null;
4144

4245
protected ?AlgorithmManagerDecoratorFactory $algorithmManagerDecoratorFactory = null;
@@ -100,6 +103,20 @@ public function clientAssertionFactory(): ClientAssertionFactory
100103
}
101104

102105

106+
public function idTokenFactory(): IdTokenFactory
107+
{
108+
return $this->idTokenFactory ??= new IdTokenFactory(
109+
$this->jwsDecoratorBuilder(),
110+
$this->jwsVerifierDecorator(),
111+
$this->jwksDecoratorFactory(),
112+
$this->jwsSerializerManagerDecorator(),
113+
$this->timestampValidationLeewayDecorator,
114+
$this->helpers(),
115+
$this->claimFactory(),
116+
);
117+
}
118+
119+
103120
public function helpers(): Helpers
104121
{
105122
return $this->helpers ??= new Helpers();
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\OpenID\Core\Factories;
6+
7+
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
8+
use SimpleSAML\OpenID\Core\IdToken;
9+
use SimpleSAML\OpenID\Jwk\JwkDecorator;
10+
use SimpleSAML\OpenID\Jws\Factories\ParsedJwsFactory;
11+
12+
class IdTokenFactory extends ParsedJwsFactory
13+
{
14+
public function fromToken(string $token): IdToken
15+
{
16+
return new IdToken(
17+
$this->jwsDecoratorBuilder->fromToken($token),
18+
$this->jwsVerifierDecorator,
19+
$this->jwksDecoratorFactory,
20+
$this->jwsSerializerManagerDecorator,
21+
$this->timestampValidationLeeway,
22+
$this->helpers,
23+
$this->claimFactory,
24+
);
25+
}
26+
27+
28+
/**
29+
* @param array<non-empty-string,mixed> $payload
30+
* @param array<non-empty-string,mixed> $header
31+
* @throws \SimpleSAML\OpenID\Exceptions\JwsException
32+
*/
33+
public function fromData(
34+
JwkDecorator $signingKey,
35+
SignatureAlgorithmEnum $signatureAlgorithm,
36+
array $payload,
37+
array $header,
38+
): IdToken {
39+
return new IdToken(
40+
$this->jwsDecoratorBuilder->fromData(
41+
$signingKey,
42+
$signatureAlgorithm,
43+
$payload,
44+
$header,
45+
),
46+
$this->jwsVerifierDecorator,
47+
$this->jwksDecoratorFactory,
48+
$this->jwsSerializerManagerDecorator,
49+
$this->timestampValidationLeeway,
50+
$this->helpers,
51+
$this->claimFactory,
52+
);
53+
}
54+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Test\OpenID\Core\Factories;
6+
7+
use Jose\Component\Signature\JWS;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\UsesClass;
10+
use PHPUnit\Framework\MockObject\MockObject;
11+
use PHPUnit\Framework\TestCase;
12+
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
13+
use SimpleSAML\OpenID\Core\Factories\IdTokenFactory;
14+
use SimpleSAML\OpenID\Core\IdToken;
15+
use SimpleSAML\OpenID\Decorators\DateIntervalDecorator;
16+
use SimpleSAML\OpenID\Factories\ClaimFactory;
17+
use SimpleSAML\OpenID\Helpers;
18+
use SimpleSAML\OpenID\Jwk\JwkDecorator;
19+
use SimpleSAML\OpenID\Jwks\Factories\JwksDecoratorFactory;
20+
use SimpleSAML\OpenID\Jws\Factories\ParsedJwsFactory;
21+
use SimpleSAML\OpenID\Jws\JwsDecorator;
22+
use SimpleSAML\OpenID\Jws\JwsDecoratorBuilder;
23+
use SimpleSAML\OpenID\Jws\JwsVerifierDecorator;
24+
use SimpleSAML\OpenID\Jws\ParsedJws;
25+
use SimpleSAML\OpenID\Serializers\JwsSerializerManagerDecorator;
26+
27+
#[CoversClass(IdTokenFactory::class)]
28+
#[UsesClass(ParsedJwsFactory::class)]
29+
#[UsesClass(ParsedJws::class)]
30+
#[UsesClass(IdToken::class)]
31+
final class IdTokenFactoryTest extends TestCase
32+
{
33+
protected MockObject $jwsDecoratorBuilderMock;
34+
35+
protected MockObject $jwsVerifierDecoratorMock;
36+
37+
protected MockObject $jwksDecoratorFactoryMock;
38+
39+
protected MockObject $jwsSerializerManagerDecoratorMock;
40+
41+
protected MockObject $dateIntervalDecoratorMock;
42+
43+
protected MockObject $helpersMock;
44+
45+
protected MockObject $jsonHelperMock;
46+
47+
protected MockObject $claimFactoryMock;
48+
49+
protected array $expiredPayload = [
50+
'iss' => 'https://server.example.com',
51+
'sub' => '24400320',
52+
'aud' => 's6BhdRkqt3',
53+
'nonce' => 'n-0S6_WzA2Mj',
54+
'exp' => 1311281970,
55+
'iat' => 1311280970,
56+
'auth_time' => 1311280969,
57+
'acr' => 'urn:mace:incommon:iap:silver',
58+
'amr' => ['otp'],
59+
];
60+
61+
protected array $validPayload;
62+
63+
protected MockObject $jwkDecoratorMock;
64+
65+
66+
protected function setUp(): void
67+
{
68+
$jwsMock = $this->createMock(JWS::class);
69+
$jwsMock->method('getPayload')
70+
->willReturn('json-payload-string'); // Just so we have non-empty value.
71+
72+
$jwsDecoratorMock = $this->createMock(JwsDecorator::class);
73+
$jwsDecoratorMock->method('jws')->willReturn($jwsMock);
74+
75+
$this->jwsDecoratorBuilderMock = $this->createMock(JwsDecoratorBuilder::class);
76+
$this->jwsDecoratorBuilderMock->method('fromToken')->willReturn($jwsDecoratorMock);
77+
$this->jwsDecoratorBuilderMock->method('fromData')->willReturn($jwsDecoratorMock);
78+
79+
$this->jwsVerifierDecoratorMock = $this->createMock(JwsVerifierDecorator::class);
80+
$this->jwksDecoratorFactoryMock = $this->createMock(JwksDecoratorFactory::class);
81+
$this->jwsSerializerManagerDecoratorMock = $this->createMock(JwsSerializerManagerDecorator::class);
82+
$this->dateIntervalDecoratorMock = $this->createMock(DateIntervalDecorator::class);
83+
84+
$this->helpersMock = $this->createMock(Helpers::class);
85+
$this->jsonHelperMock = $this->createMock(Helpers\Json::class);
86+
$this->helpersMock->method('json')->willReturn($this->jsonHelperMock);
87+
$typeHelperMock = $this->createMock(Helpers\Type::class);
88+
$this->helpersMock->method('type')->willReturn($typeHelperMock);
89+
90+
$typeHelperMock->method('ensureNonEmptyString')->willReturnArgument(0);
91+
$typeHelperMock->method('ensureInt')->willReturnArgument(0);
92+
$typeHelperMock->method('ensureArrayWithValuesAsNonEmptyStrings')->willReturnArgument(0);
93+
$typeHelperMock->method('enforceUri')->willReturnArgument(0);
94+
$typeHelperMock->method('ensureArrayWithKeysAndValuesAsNonEmptyStrings')
95+
->willReturnArgument(0);
96+
97+
$this->claimFactoryMock = $this->createMock(ClaimFactory::class);
98+
99+
$this->validPayload = $this->expiredPayload;
100+
$this->validPayload['exp'] = time() + 3600;
101+
102+
$this->jwkDecoratorMock = $this->createMock(JwkDecorator::class);
103+
}
104+
105+
106+
protected function sut(
107+
?JwsDecoratorBuilder $jwsDecoratorBuilder = null,
108+
?JwsVerifierDecorator $jwsVerifierDecorator = null,
109+
?JwksDecoratorFactory $jwksDecoratorFactory = null,
110+
?JwsSerializerManagerDecorator $jwsSerializerManagerDecorator = null,
111+
?DateIntervalDecorator $dateIntervalDecorator = null,
112+
?Helpers $helpers = null,
113+
?ClaimFactory $claimFactory = null,
114+
): IdTokenFactory {
115+
$jwsDecoratorBuilder ??= $this->jwsDecoratorBuilderMock;
116+
$jwsVerifierDecorator ??= $this->jwsVerifierDecoratorMock;
117+
$jwksDecoratorFactory ??= $this->jwksDecoratorFactoryMock;
118+
$jwsSerializerManagerDecorator ??= $this->jwsSerializerManagerDecoratorMock;
119+
$dateIntervalDecorator ??= $this->dateIntervalDecoratorMock;
120+
$helpers ??= $this->helpersMock;
121+
$claimFactory ??= $this->claimFactoryMock;
122+
123+
return new IdTokenFactory(
124+
$jwsDecoratorBuilder,
125+
$jwsVerifierDecorator,
126+
$jwksDecoratorFactory,
127+
$jwsSerializerManagerDecorator,
128+
$dateIntervalDecorator,
129+
$helpers,
130+
$claimFactory,
131+
);
132+
}
133+
134+
135+
public function testCanCreateInstance(): void
136+
{
137+
$this->assertInstanceOf(IdTokenFactory::class, $this->sut());
138+
}
139+
140+
141+
public function testCanBuildFromToken(): void
142+
{
143+
$this->jsonHelperMock->method('decode')->willReturn($this->validPayload);
144+
145+
$this->assertInstanceOf(
146+
IdToken::class,
147+
$this->sut()->fromToken('token'),
148+
);
149+
}
150+
151+
152+
public function testCanBuildFromData(): void
153+
{
154+
$this->jsonHelperMock->method('decode')->willReturn($this->validPayload);
155+
156+
$this->assertInstanceOf(
157+
IdToken::class,
158+
$this->sut()->fromData(
159+
$this->jwkDecoratorMock,
160+
SignatureAlgorithmEnum::ES256,
161+
$this->validPayload,
162+
[],
163+
),
164+
);
165+
}
166+
}

0 commit comments

Comments
 (0)