25
25
import java .util .ArrayList ;
26
26
import java .util .List ;
27
27
import java .util .Map ;
28
+ import java .util .function .Consumer ;
28
29
29
30
import com .nimbusds .jose .jwk .JWKSet ;
30
31
import com .nimbusds .jose .jwk .RSAKey ;
96
97
import org .springframework .web .server .WebSession ;
97
98
import org .springframework .web .server .adapter .WebHttpHandlerBuilder ;
98
99
100
+ import static org .assertj .core .api .Assertions .assertThat ;
99
101
import static org .hamcrest .Matchers .containsString ;
100
102
import static org .mockito .ArgumentMatchers .any ;
101
103
import static org .mockito .BDDMockito .given ;
@@ -291,6 +293,29 @@ void logoutWhenSelfRemoteLogoutUriThenUses() {
291
293
this .test .get ().uri ("/token/logout" ).cookie ("SESSION" , sessionId ).exchange ().expectStatus ().isUnauthorized ();
292
294
}
293
295
296
+ @ Test
297
+ void logoutWhenDifferentCookieNameThenUses () {
298
+ this .spring .register (OidcProviderConfig .class , CookieConfig .class ).autowire ();
299
+ String registrationId = this .clientRegistration .getRegistrationId ();
300
+ String sessionId = login ();
301
+ String logoutToken = this .test .get ()
302
+ .uri ("/token/logout" )
303
+ .cookie ("SESSION" , sessionId )
304
+ .exchange ()
305
+ .expectStatus ()
306
+ .isOk ()
307
+ .returnResult (String .class )
308
+ .getResponseBody ()
309
+ .blockFirst ();
310
+ this .test .post ()
311
+ .uri (this .web .url ("/logout/connect/back-channel/" + registrationId ).toString ())
312
+ .body (BodyInserters .fromFormData ("logout_token" , logoutToken ))
313
+ .exchange ()
314
+ .expectStatus ()
315
+ .isOk ();
316
+ this .test .get ().uri ("/token/logout" ).cookie ("SESSION" , sessionId ).exchange ().expectStatus ().isUnauthorized ();
317
+ }
318
+
294
319
@ Test
295
320
void logoutWhenRemoteLogoutFailsThenReportsPartialLogout () {
296
321
this .spring .register (WebServerConfig .class , OidcProviderConfig .class , WithBrokenLogoutConfig .class ).autowire ();
@@ -491,6 +516,51 @@ SecurityWebFilterChain filters(ServerHttpSecurity http) throws Exception {
491
516
492
517
}
493
518
519
+ @ Configuration
520
+ @ EnableWebFluxSecurity
521
+ @ Import (RegistrationConfig .class )
522
+ static class CookieConfig {
523
+
524
+ private final MockWebServer server = new MockWebServer ();
525
+
526
+ @ Bean
527
+ @ Order (1 )
528
+ SecurityWebFilterChain filters (ServerHttpSecurity http ) throws Exception {
529
+ // @formatter:off
530
+ http
531
+ .authorizeExchange ((authorize ) -> authorize .anyExchange ().authenticated ())
532
+ .oauth2Login (Customizer .withDefaults ())
533
+ .oidcLogout ((oidc ) -> oidc
534
+ .backChannel ((backchannel ) -> backchannel
535
+ .sessionLogout ((logout ) -> logout .cookieName ("JSESSIONID" ))
536
+ )
537
+ );
538
+ // @formatter:on
539
+
540
+ return http .build ();
541
+ }
542
+
543
+ @ Bean
544
+ MockWebServer web (ObjectProvider <WebTestClient > web ) {
545
+ WebTestClientDispatcher dispatcher = new WebTestClientDispatcher (web );
546
+ dispatcher .setAssertion ((rr ) -> {
547
+ String cookie = rr .getHeaders ().get ("Cookie" );
548
+ if (cookie == null ) {
549
+ return ;
550
+ }
551
+ assertThat (cookie ).contains ("JSESSIONID" );
552
+ });
553
+ this .server .setDispatcher (dispatcher );
554
+ return this .server ;
555
+ }
556
+
557
+ @ PreDestroy
558
+ void shutdown () throws IOException {
559
+ this .server .shutdown ();
560
+ }
561
+
562
+ }
563
+
494
564
@ Configuration
495
565
@ EnableWebFluxSecurity
496
566
@ Import (RegistrationConfig .class )
@@ -699,12 +769,15 @@ private static class WebTestClientDispatcher extends Dispatcher {
699
769
700
770
private WebTestClient web ;
701
771
772
+ private Consumer <RecordedRequest > assertion = (rr ) -> { };
773
+
702
774
WebTestClientDispatcher (ObjectProvider <WebTestClient > web ) {
703
775
this .webProvider = web ;
704
776
}
705
777
706
778
@ Override
707
779
public MockResponse dispatch (RecordedRequest request ) throws InterruptedException {
780
+ this .assertion .accept (request );
708
781
this .web = this .webProvider .getObject ();
709
782
String method = request .getMethod ();
710
783
String path = request .getPath ();
@@ -747,6 +820,10 @@ public MockResponse dispatch(RecordedRequest request) throws InterruptedExceptio
747
820
}
748
821
}
749
822
823
+ void setAssertion (Consumer <RecordedRequest > assertion ) {
824
+ this .assertion = assertion ;
825
+ }
826
+
750
827
private String session (RecordedRequest request ) {
751
828
String cookieHeaderValue = request .getHeader ("Cookie" );
752
829
if (cookieHeaderValue == null ) {
@@ -758,6 +835,9 @@ private String session(RecordedRequest request) {
758
835
if (SESSION_COOKIE_NAME .equals (parts [0 ])) {
759
836
return parts [1 ];
760
837
}
838
+ if ("JSESSIONID" .equals (parts [0 ])) {
839
+ return parts [1 ];
840
+ }
761
841
}
762
842
return null ;
763
843
}
0 commit comments