Skip to content

Commit d25d3f5

Browse files
committed
WIP
1 parent 24bd194 commit d25d3f5

File tree

1 file changed

+189
-5
lines changed

1 file changed

+189
-5
lines changed

tests/unit/src/Services/IdTokenBuilderTest.php

Lines changed: 189 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,199 @@
44

55
namespace SimpleSAML\Test\Module\oidc\unit\Services;
66

7+
use DateTimeImmutable;
8+
use League\OAuth2\Server\Entities\UserEntityInterface;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\MockObject\MockObject;
711
use PHPUnit\Framework\TestCase;
12+
use SimpleSAML\Module\oidc\Entities\AccessTokenEntity;
13+
use SimpleSAML\Module\oidc\Entities\ClientEntity;
14+
use SimpleSAML\Module\oidc\Entities\ScopeEntity;
15+
use SimpleSAML\Module\oidc\Entities\UserEntity;
16+
use SimpleSAML\Module\oidc\ModuleConfig;
17+
use SimpleSAML\Module\oidc\Services\IdTokenBuilder;
18+
use SimpleSAML\Module\oidc\Utils\ClaimTranslatorExtractor;
19+
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
20+
use SimpleSAML\OpenID\Codebooks\ClaimsEnum;
21+
use SimpleSAML\OpenID\Core;
22+
use SimpleSAML\OpenID\Core\Factories\IdTokenFactory;
23+
use SimpleSAML\OpenID\Core\IdToken;
24+
use SimpleSAML\OpenID\ValueAbstracts\SignatureKeyPair;
25+
use SimpleSAML\OpenID\ValueAbstracts\SignatureKeyPairBag;
826

9-
/**
10-
* @covers \SimpleSAML\Module\oidc\Services\IdTokenBuilder
11-
*/
27+
#[CoversClass(IdTokenBuilder::class)]
1228
class IdTokenBuilderTest extends TestCase
1329
{
14-
public function testIncomplete(): never
30+
protected MockObject $claimTranslatorExtractorMock;
31+
protected MockObject $coreMock;
32+
protected MockObject $moduleConfigMock;
33+
protected MockObject $protocolSignatureKeyBagMock;
34+
protected MockObject $protocolSignatureKeyPairMock;
35+
protected MockObject $idTokenFactoryMock;
36+
protected MockObject $userEntityMock;
37+
protected MockObject $accessTokenEntityMock;
38+
protected MockObject $clientEntityMock;
39+
protected MockObject $accessTokenExpiryDateTimeMock;
40+
protected MockObject $scopeEntityMock;
41+
42+
protected function setUp(): void
43+
{
44+
$this->claimTranslatorExtractorMock = $this->createMock(ClaimTranslatorExtractor::class);
45+
$this->coreMock = $this->createMock(Core::class);
46+
$this->moduleConfigMock = $this->createMock(ModuleConfig::class);
47+
48+
$this->protocolSignatureKeyBagMock = $this->createMock(SignatureKeyPairBag::class);
49+
50+
$this->moduleConfigMock->method('getProtocolSignatureKeyPairBag')
51+
->willReturn($this->protocolSignatureKeyBagMock);
52+
53+
$this->protocolSignatureKeyPairMock = $this->createMock(SignatureKeyPair::class);
54+
$this->protocolSignatureKeyPairMock->method('getSignatureAlgorithm')
55+
->willReturn(SignatureAlgorithmEnum::RS256);
56+
57+
$this->protocolSignatureKeyBagMock->method('getFirstOrFail')
58+
->willReturn($this->protocolSignatureKeyPairMock);
59+
60+
61+
$this->idTokenFactoryMock = $this->createMock(IdTokenFactory::class);
62+
$this->coreMock->method('idTokenFactory')->willReturn($this->idTokenFactoryMock);
63+
64+
$this->userEntityMock = $this->createMock(UserEntity::class);
65+
$this->accessTokenEntityMock = $this->createMock(AccessTokenEntity::class);
66+
67+
68+
$this->clientEntityMock = $this->createMock(ClientEntity::class);
69+
$this->accessTokenEntityMock->method('getClient')->willReturn($this->clientEntityMock);
70+
71+
$this->accessTokenExpiryDateTimeMock = $this->createMock(DateTimeImmutable::class);
72+
$this->accessTokenEntityMock->method('getExpiryDateTime')
73+
->willReturn($this->accessTokenExpiryDateTimeMock);
74+
75+
$this->scopeEntityMock = $this->createMock(ScopeEntity::class);
76+
$this->accessTokenEntityMock->method('getScopes')->willReturn([$this->scopeEntityMock]);
77+
}
78+
79+
protected function sut(
80+
?ClaimTranslatorExtractor $claimTranslatorExtractor = null,
81+
?Core $core = null,
82+
?ModuleConfig $moduleConfig = null,
83+
): IdTokenBuilder {
84+
$claimTranslatorExtractor ??= $this->claimTranslatorExtractorMock;
85+
$core ??= $this->coreMock;
86+
$moduleConfig ??= $this->moduleConfigMock;
87+
88+
return new IdTokenBuilder(
89+
$claimTranslatorExtractor,
90+
$core,
91+
$moduleConfig,
92+
);
93+
}
94+
95+
public function testCanCreateInstance(): void
1596
{
16-
$this->markTestIncomplete();
97+
$this->assertInstanceOf(IdTokenBuilder::class, $this->sut());
98+
}
99+
100+
public function testCanBuild(): void
101+
{
102+
$this->moduleConfigMock->expects($this->once())->method('getIssuer')
103+
->willReturn('issuer');
104+
$this->idTokenFactoryMock->expects($this->once())->method('fromData')
105+
->with(
106+
$this->anything(),
107+
SignatureAlgorithmEnum::RS256,
108+
$this->arrayHasKey(ClaimsEnum::Iss->value),
109+
);
110+
111+
$this->claimTranslatorExtractorMock->expects($this->once())
112+
->method('extract')
113+
->willReturn(['foo' => 'bar']);
114+
115+
$this->claimTranslatorExtractorMock->expects($this->once())
116+
->method('extractAdditionalIdTokenClaims')
117+
->willReturn(['additional' => 'claim']);
118+
119+
$this->assertInstanceOf(
120+
IdToken::class,
121+
$this->sut()->buildFor(
122+
$this->userEntityMock,
123+
$this->accessTokenEntityMock,
124+
true,
125+
true,
126+
null,
127+
null,
128+
null,
129+
null,
130+
),
131+
);
132+
}
133+
134+
public function testWillNegotiateIdTokenSignatureAlgorithm(): void
135+
{
136+
$this->clientEntityMock->method('getIdTokenSignedResponseAlg')
137+
->willReturn(SignatureAlgorithmEnum::ES256->value);
138+
139+
$ecSignatureKeyPairMock = $this->createMock(SignatureKeyPair::class);
140+
$ecSignatureKeyPairMock->method('getSignatureAlgorithm')
141+
->willReturn(SignatureAlgorithmEnum::ES256);
142+
143+
$this->protocolSignatureKeyBagMock->expects($this->once())
144+
->method('getFirstByAlgorithmOrFail')
145+
->with(SignatureAlgorithmEnum::ES256)
146+
->willReturn($ecSignatureKeyPairMock);
147+
148+
$this->assertInstanceOf(
149+
IdToken::class,
150+
$this->sut()->buildFor(
151+
$this->userEntityMock,
152+
$this->accessTokenEntityMock,
153+
true,
154+
true,
155+
null,
156+
null,
157+
null,
158+
null,
159+
),
160+
);
161+
}
162+
163+
public function testThrowsForInvalidUserEntity(): void
164+
{
165+
$userEntityInterfaceMock = $this->createMock(UserEntityInterface::class);
166+
$this->expectException(\RuntimeException::class);
167+
$this->expectExceptionMessage('ClaimSetInterface');
168+
169+
$this->sut()->buildFor(
170+
$userEntityInterfaceMock,
171+
$this->accessTokenEntityMock,
172+
true,
173+
true,
174+
null,
175+
null,
176+
null,
177+
null,
178+
);
179+
}
180+
181+
public function testThrowsForInvalidClientEntity(): void
182+
{
183+
$accessTokenEntityMock = $this->createMock(AccessTokenEntity::class);
184+
$accessTokenEntityMock->method('getClient')->willReturn(
185+
$this->createMock(\League\OAuth2\Server\Entities\ClientEntityInterface::class),
186+
);
187+
188+
$this->expectException(\RuntimeException::class);
189+
$this->expectExceptionMessage('ClientEntity');
190+
191+
$this->sut()->buildFor(
192+
$this->userEntityMock,
193+
$accessTokenEntityMock,
194+
true,
195+
true,
196+
null,
197+
null,
198+
null,
199+
null,
200+
);
17201
}
18202
}

0 commit comments

Comments
 (0)