88use PHPUnit \Framework \Attributes \CoversClass ;
99use PHPUnit \Framework \MockObject \MockObject ;
1010use PHPUnit \Framework \TestCase ;
11+ use SimpleSAML \Module \oidc \Helpers as OidcHelpers ;
12+ use SimpleSAML \Module \oidc \Helpers \Random as OidcRandom ;
1113use SimpleSAML \Module \oidc \ModuleConfig ;
1214use SimpleSAML \Module \oidc \Services \LoggerService ;
1315use SimpleSAML \Module \oidc \Services \NonceService ;
@@ -34,6 +36,8 @@ class NonceServiceTest extends TestCase
3436 protected MockObject $ signatureKeyPairMock ;
3537 protected MockObject $ helpersMock ;
3638 protected MockObject $ dateTimeHelperMock ;
39+ protected MockObject $ oidcHelpersMock ;
40+ protected MockObject $ oidcRandomMock ;
3741
3842 public function setUp (): void
3943 {
@@ -44,10 +48,13 @@ public function setUp(): void
4448 $ this ->parsedJwsMock = $ this ->createMock (ParsedJws::class);
4549 $ this ->helpersMock = $ this ->createMock (Helpers::class);
4650 $ this ->dateTimeHelperMock = $ this ->createMock (DateTime::class);
51+ $ this ->oidcHelpersMock = $ this ->createMock (OidcHelpers::class);
52+ $ this ->oidcRandomMock = $ this ->createMock (OidcRandom::class);
4753
4854 $ this ->jwsMock ->method ('parsedJwsFactory ' )->willReturn ($ this ->parsedJwsFactoryMock );
4955 $ this ->jwsMock ->method ('helpers ' )->willReturn ($ this ->helpersMock );
5056 $ this ->helpersMock ->method ('dateTime ' )->willReturn ($ this ->dateTimeHelperMock );
57+ $ this ->oidcHelpersMock ->method ('random ' )->willReturn ($ this ->oidcRandomMock );
5158
5259 $ this ->signatureKeyPairMock = $ this ->createMock (SignatureKeyPair::class);
5360 $ this ->signatureKeyPairBagMock = $ this ->createMock (SignatureKeyPairBag::class);
@@ -57,8 +64,10 @@ public function setUp(): void
5764
5865 public function testGenerateNonce (): void
5966 {
60- $ this ->dateTimeHelperMock ->method ('getUtc ' )->willReturn (new \DateTimeImmutable ('2024-01-01 00:00:00 ' ));
67+ $ currentDateTime = new \DateTimeImmutable ('2024-01-01 00:00:00 ' );
68+ $ this ->dateTimeHelperMock ->method ('getUtc ' )->willReturn ($ currentDateTime );
6169 $ this ->moduleConfigMock ->method ('getIssuer ' )->willReturn ('https://issuer.example.com ' );
70+ $ this ->moduleConfigMock ->method ('getVciNonceTtl ' )->willReturn (new \DateInterval ('PT5M ' ));
6271
6372 $ privateKeyMock = $ this ->createMock (JwkDecorator::class);
6473 $ keyPairMock = $ this ->createMock (KeyPair::class);
@@ -67,13 +76,33 @@ public function testGenerateNonce(): void
6776 $ this ->signatureKeyPairMock ->method ('getKeyPair ' )->willReturn ($ keyPairMock );
6877 $ this ->signatureKeyPairMock ->method ('getSignatureAlgorithm ' )->willReturn (SignatureAlgorithmEnum::ES256 );
6978
79+ $ this ->oidcRandomMock ->expects ($ this ->once ())
80+ ->method ('getIdentifier ' )
81+ ->with (16 )
82+ ->willReturn ('mocked_random_nonce ' );
83+
7084 $ this ->parsedJwsFactoryMock ->expects ($ this ->once ())
7185 ->method ('fromData ' )
86+ ->with (
87+ $ this ->anything (),
88+ $ this ->anything (),
89+ $ this ->callback (function (array $ payload ) use ($ currentDateTime ): bool {
90+ return $ payload ['iat ' ] === $ currentDateTime ->getTimestamp ()
91+ && $ payload ['exp ' ] === $ currentDateTime ->getTimestamp () + 300
92+ && $ payload ['nonce_val ' ] === 'mocked_random_nonce ' ;
93+ }),
94+ $ this ->anything (),
95+ )
7296 ->willReturn ($ this ->parsedJwsMock );
7397
7498 $ this ->parsedJwsMock ->method ('getToken ' )->willReturn ('mocked_token ' );
7599
76- $ sut = new NonceService ($ this ->jwsMock , $ this ->moduleConfigMock , $ this ->loggerServiceMock );
100+ $ sut = new NonceService (
101+ $ this ->jwsMock ,
102+ $ this ->moduleConfigMock ,
103+ $ this ->loggerServiceMock ,
104+ $ this ->oidcHelpersMock ,
105+ );
77106 $ nonce = $ sut ->generateNonce ();
78107
79108 $ this ->assertEquals ('mocked_token ' , $ nonce );
@@ -98,7 +127,12 @@ public function testValidateNonceSuccess(): void
98127 $ this ->parsedJwsMock ->method ('getExpirationTime ' )
99128 ->willReturn ((new \DateTimeImmutable ('2024-01-01 00:00:00 ' ))->getTimestamp () + 100 );
100129
101- $ sut = new NonceService ($ this ->jwsMock , $ this ->moduleConfigMock , $ this ->loggerServiceMock );
130+ $ sut = new NonceService (
131+ $ this ->jwsMock ,
132+ $ this ->moduleConfigMock ,
133+ $ this ->loggerServiceMock ,
134+ $ this ->oidcHelpersMock ,
135+ );
102136 $ this ->assertTrue ($ sut ->validateNonce ('valid_token ' ));
103137 }
104138
@@ -119,7 +153,12 @@ public function testValidateNonceInvalidIssuer(): void
119153 $ this ->parsedJwsMock ->method ('getIssuer ' )->willReturn ('https://other.example.com ' );
120154 $ this ->moduleConfigMock ->method ('getIssuer ' )->willReturn ('https://issuer.example.com ' );
121155
122- $ sut = new NonceService ($ this ->jwsMock , $ this ->moduleConfigMock , $ this ->loggerServiceMock );
156+ $ sut = new NonceService (
157+ $ this ->jwsMock ,
158+ $ this ->moduleConfigMock ,
159+ $ this ->loggerServiceMock ,
160+ $ this ->oidcHelpersMock ,
161+ );
123162 $ this ->assertFalse ($ sut ->validateNonce ('invalid_issuer_token ' ));
124163 }
125164
@@ -142,7 +181,12 @@ public function testValidateNonceExpired(): void
142181 $ this ->parsedJwsMock ->method ('getExpirationTime ' )
143182 ->willReturn ((new \DateTimeImmutable ('2024-01-01 00:00:00 ' ))->getTimestamp () - 10 );
144183
145- $ sut = new NonceService ($ this ->jwsMock , $ this ->moduleConfigMock , $ this ->loggerServiceMock );
184+ $ sut = new NonceService (
185+ $ this ->jwsMock ,
186+ $ this ->moduleConfigMock ,
187+ $ this ->loggerServiceMock ,
188+ $ this ->oidcHelpersMock ,
189+ );
146190 $ this ->assertFalse ($ sut ->validateNonce ('expired_token ' ));
147191 }
148192}
0 commit comments