@@ -70,9 +70,18 @@ public function testAuthorize(): void {
7070 ->with ('MyClientId ' )
7171 ->willReturn ($ client );
7272 $ this ->session
73- ->expects ($ this ->once ( ))
73+ ->expects ($ this ->exactly ( 3 ))
7474 ->method ('set ' )
75- ->with ('oauth.state ' , 'MyState ' );
75+ ->willReturnCallback (function (string $ key , string $ value ): void {
76+ switch ([$ key , $ value ]) {
77+ case ['oauth.state ' , 'MyState ' ]:
78+ case ['oauth.code_challenge ' , '' ]:
79+ case ['oauth.code_challenge_method ' , '' ]:
80+ break ;
81+ default :
82+ throw new LogicException ();
83+ }
84+ });
7685 $ this ->urlGenerator
7786 ->expects ($ this ->once ())
7887 ->method ('linkToRouteAbsolute ' )
@@ -104,11 +113,13 @@ public function testAuthorizeSkipPicker(): void {
104113 ->with ('MyClientId ' )
105114 ->willReturn ($ client );
106115 $ this ->session
107- ->expects (static ::exactly (2 ))
116+ ->expects (static ::exactly (4 ))
108117 ->method ('set ' )
109118 ->willReturnCallback (function (string $ key , string $ value ): void {
110119 switch ([$ key , $ value ]) {
111120 case ['oauth.state ' , 'MyState ' ]:
121+ case ['oauth.code_challenge ' , '' ]:
122+ case ['oauth.code_challenge_method ' , '' ]:
112123 case [ClientFlowLoginController::STATE_NAME , 'MyStateToken ' ]:
113124 /* Expected */
114125 break ;
@@ -182,6 +193,59 @@ public function testAuthorizeRejectsCodeChallengeMethodWithoutChallenge(): void
182193 $ this ->assertEquals ($ expected , $ this ->loginRedirectorController ->authorize ('MyClientId ' , 'MyState ' , 'code ' , '' , '' , 'S256 ' ));
183194 }
184195
196+ public function testAuthorizeRejectsPkceWithoutMethodBecausePlainIsUnsupported (): void {
197+ $ client = new Client ();
198+ $ client ->setClientIdentifier ('MyClientIdentifier ' );
199+ $ client ->setRedirectUri ('http://foo.bar ' );
200+ $ this ->clientMapper
201+ ->expects ($ this ->once ())
202+ ->method ('getByIdentifier ' )
203+ ->with ('MyClientId ' )
204+ ->willReturn ($ client );
205+ $ this ->session
206+ ->expects ($ this ->never ())
207+ ->method ('set ' );
208+
209+ $ codeChallenge = str_repeat ('a ' , 43 );
210+ $ expected = new RedirectResponse ('http://foo.bar?error=invalid_request&error_description=Transform+algorithm+not+supported&state=MyState ' );
211+ $ this ->assertEquals ($ expected , $ this ->loginRedirectorController ->authorize ('MyClientId ' , 'MyState ' , 'code ' , '' , $ codeChallenge ));
212+ }
213+
214+ public function testAuthorizeRejectsUnsupportedCodeChallengeMethod (): void {
215+ $ client = new Client ();
216+ $ client ->setClientIdentifier ('MyClientIdentifier ' );
217+ $ client ->setRedirectUri ('http://foo.bar ' );
218+ $ this ->clientMapper
219+ ->expects ($ this ->once ())
220+ ->method ('getByIdentifier ' )
221+ ->with ('MyClientId ' )
222+ ->willReturn ($ client );
223+ $ this ->session
224+ ->expects ($ this ->never ())
225+ ->method ('set ' );
226+
227+ $ codeChallenge = str_repeat ('a ' , 43 );
228+ $ expected = new RedirectResponse ('http://foo.bar?error=invalid_request&error_description=Transform+algorithm+not+supported&state=MyState ' );
229+ $ this ->assertEquals ($ expected , $ this ->loginRedirectorController ->authorize ('MyClientId ' , 'MyState ' , 'code ' , '' , $ codeChallenge , 'plain ' ));
230+ }
231+
232+ public function testAuthorizeRejectsInvalidCodeChallengeFormat (): void {
233+ $ client = new Client ();
234+ $ client ->setClientIdentifier ('MyClientIdentifier ' );
235+ $ client ->setRedirectUri ('http://foo.bar ' );
236+ $ this ->clientMapper
237+ ->expects ($ this ->once ())
238+ ->method ('getByIdentifier ' )
239+ ->with ('MyClientId ' )
240+ ->willReturn ($ client );
241+ $ this ->session
242+ ->expects ($ this ->never ())
243+ ->method ('set ' );
244+
245+ $ expected = new RedirectResponse ('http://foo.bar?error=invalid_request&error_description=Invalid+code_challenge&state=MyState ' );
246+ $ this ->assertEquals ($ expected , $ this ->loginRedirectorController ->authorize ('MyClientId ' , 'MyState ' , 'code ' , '' , 'short ' , 'S256 ' ));
247+ }
248+
185249 public function testAuthorizeWithLegacyOcClient (): void {
186250 $ client = new Client ();
187251 $ client ->setClientIdentifier ('MyClientIdentifier ' );
@@ -192,9 +256,18 @@ public function testAuthorizeWithLegacyOcClient(): void {
192256 ->with ('MyClientId ' )
193257 ->willReturn ($ client );
194258 $ this ->session
195- ->expects ($ this ->once ( ))
259+ ->expects ($ this ->exactly ( 3 ))
196260 ->method ('set ' )
197- ->with ('oauth.state ' , 'MyState ' );
261+ ->willReturnCallback (function (string $ key , string $ value ): void {
262+ switch ([$ key , $ value ]) {
263+ case ['oauth.state ' , 'MyState ' ]:
264+ case ['oauth.code_challenge ' , '' ]:
265+ case ['oauth.code_challenge_method ' , '' ]:
266+ break ;
267+ default :
268+ throw new LogicException ();
269+ }
270+ });
198271 $ this ->urlGenerator
199272 ->expects ($ this ->once ())
200273 ->method ('linkToRouteAbsolute ' )
@@ -225,9 +298,18 @@ public function testAuthorizeNotForwardingUntrustedURIs(): void {
225298 ->with ('MyClientId ' )
226299 ->willReturn ($ client );
227300 $ this ->session
228- ->expects ($ this ->once ( ))
301+ ->expects ($ this ->exactly ( 3 ))
229302 ->method ('set ' )
230- ->with ('oauth.state ' , 'MyState ' );
303+ ->willReturnCallback (function (string $ key , string $ value ): void {
304+ switch ([$ key , $ value ]) {
305+ case ['oauth.state ' , 'MyState ' ]:
306+ case ['oauth.code_challenge ' , '' ]:
307+ case ['oauth.code_challenge_method ' , '' ]:
308+ break ;
309+ default :
310+ throw new LogicException ();
311+ }
312+ });
231313 $ this ->urlGenerator
232314 ->expects ($ this ->once ())
233315 ->method ('linkToRouteAbsolute ' )
0 commit comments