64
64
import org .springframework .security .oauth2 .client .registration .InMemoryReactiveClientRegistrationRepository ;
65
65
import org .springframework .security .oauth2 .client .registration .ReactiveClientRegistrationRepository ;
66
66
import org .springframework .security .oauth2 .client .registration .TestClientRegistrations ;
67
+ import org .springframework .security .oauth2 .client .userinfo .DefaultReactiveOAuth2UserService ;
68
+ import org .springframework .security .oauth2 .client .userinfo .OAuth2UserRequest ;
67
69
import org .springframework .security .oauth2 .client .userinfo .ReactiveOAuth2UserService ;
68
70
import org .springframework .security .oauth2 .client .web .server .DefaultServerOAuth2AuthorizationRequestResolver ;
69
71
import org .springframework .security .oauth2 .client .web .server .ServerAuthorizationRequestRepository ;
84
86
import org .springframework .security .oauth2 .core .oidc .endpoint .OidcParameterNames ;
85
87
import org .springframework .security .oauth2 .core .oidc .user .OidcUser ;
86
88
import org .springframework .security .oauth2 .core .oidc .user .TestOidcUsers ;
89
+ import org .springframework .security .oauth2 .core .user .DefaultOAuth2User ;
87
90
import org .springframework .security .oauth2 .core .user .OAuth2User ;
88
91
import org .springframework .security .oauth2 .core .user .TestOAuth2Users ;
89
92
import org .springframework .security .oauth2 .jwt .Jwt ;
@@ -664,6 +667,41 @@ public void oauth2LoginWhenDefaultsThenNoOidcSessionRegistry() {
664
667
.block ()).isEmpty ();
665
668
}
666
669
670
+ @ Test
671
+ public void oauth2LoginWhenOauth2UserServiceBeanPresent () {
672
+ this .spring .register (OAuth2LoginWithMultipleClientRegistrations .class , OAuth2LoginWithOauth2UserService .class )
673
+ .autowire ();
674
+ WebTestClient webTestClient = WebTestClientBuilder .bindToWebFilters (this .springSecurity ).build ();
675
+ OAuth2LoginWithOauth2UserService config = this .spring .getContext ()
676
+ .getBean (OAuth2LoginWithOauth2UserService .class );
677
+ OAuth2AuthorizationRequest request = TestOAuth2AuthorizationRequests .request ().scope ("openid" ).build ();
678
+ OAuth2AuthorizationResponse response = TestOAuth2AuthorizationResponses .success ().build ();
679
+ OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange (request , response );
680
+ OAuth2AccessToken accessToken = TestOAuth2AccessTokens .scopes ("openid" );
681
+ OAuth2AuthorizationCodeAuthenticationToken token = new OAuth2AuthorizationCodeAuthenticationToken (google ,
682
+ exchange , accessToken );
683
+ ServerAuthenticationConverter converter = config .authenticationConverter ;
684
+ given (converter .convert (any ())).willReturn (Mono .just (token ));
685
+ ServerSecurityContextRepository securityContextRepository = config .securityContextRepository ;
686
+ given (securityContextRepository .save (any (), any ())).willReturn (Mono .empty ());
687
+ given (securityContextRepository .load (any ())).willReturn (authentication (token ));
688
+ Map <String , Object > additionalParameters = new HashMap <>();
689
+ additionalParameters .put (OidcParameterNames .ID_TOKEN , "id-token" );
690
+ OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse .withToken (accessToken .getTokenValue ())
691
+ .tokenType (accessToken .getTokenType ())
692
+ .scopes (accessToken .getScopes ())
693
+ .additionalParameters (additionalParameters )
694
+ .build ();
695
+ ReactiveOAuth2AccessTokenResponseClient <OAuth2AuthorizationCodeGrantRequest > tokenResponseClient = config .tokenResponseClient ;
696
+ given (tokenResponseClient .getTokenResponse (any ())).willReturn (Mono .just (accessTokenResponse ));
697
+ ReactiveOAuth2UserService <OAuth2UserRequest , OAuth2User > userService = config .reactiveOAuth2UserService ;
698
+ given (userService .loadUser (any ())).willReturn (Mono
699
+ .just (new DefaultOAuth2User (AuthorityUtils .createAuthorityList ("USER" ), Map .of ("sub" , "subject" ), "sub" )));
700
+ webTestClient .get ().uri ("/login/oauth2/code/google" ).exchange ().expectStatus ().is3xxRedirection ();
701
+ verify (userService ).loadUser (any ());
702
+
703
+ }
704
+
667
705
Mono <SecurityContext > authentication (Authentication authentication ) {
668
706
SecurityContext context = new SecurityContextImpl ();
669
707
context .setAuthentication (authentication );
@@ -674,6 +712,51 @@ <T> T getBean(Class<T> beanClass) {
674
712
return this .spring .getContext ().getBean (beanClass );
675
713
}
676
714
715
+ @ Configuration
716
+ static class OAuth2LoginWithOauth2UserService {
717
+
718
+ ReactiveOAuth2AccessTokenResponseClient <OAuth2AuthorizationCodeGrantRequest > tokenResponseClient = mock (
719
+ ReactiveOAuth2AccessTokenResponseClient .class );
720
+
721
+ ReactiveOAuth2UserService <OAuth2UserRequest , OAuth2User > reactiveOAuth2UserService = mock (
722
+ DefaultReactiveOAuth2UserService .class );
723
+
724
+ ServerAuthenticationConverter authenticationConverter = mock (ServerAuthenticationConverter .class );
725
+
726
+ ServerSecurityContextRepository securityContextRepository = mock (ServerSecurityContextRepository .class );
727
+
728
+ @ Bean
729
+ SecurityWebFilterChain springSecurity (ServerHttpSecurity http ) {
730
+ http .authorizeExchange ((authorize ) -> authorize .anyExchange ().authenticated ())
731
+ .oauth2Login ((c ) -> c .authenticationConverter (this .authenticationConverter )
732
+ .securityContextRepository (this .securityContextRepository ));
733
+ return http .build ();
734
+ }
735
+
736
+ @ Bean
737
+ ReactiveOAuth2UserService <OAuth2UserRequest , OAuth2User > customOAuth2UserService () {
738
+ return this .reactiveOAuth2UserService ;
739
+ }
740
+
741
+ @ Bean
742
+ ReactiveJwtDecoderFactory <ClientRegistration > jwtDecoderFactory () {
743
+ return (clientRegistration ) -> (token ) -> {
744
+ Map <String , Object > claims = new HashMap <>();
745
+ claims .put (IdTokenClaimNames .SUB , "subject" );
746
+ claims .put (IdTokenClaimNames .ISS , "http://localhost/issuer" );
747
+ claims .put (IdTokenClaimNames .AUD , Collections .singletonList ("client" ));
748
+ claims .put (IdTokenClaimNames .AZP , "client" );
749
+ return Mono .just (TestJwts .jwt ().claims ((c ) -> c .putAll (claims )).build ());
750
+ };
751
+ }
752
+
753
+ @ Bean
754
+ ReactiveOAuth2AccessTokenResponseClient <OAuth2AuthorizationCodeGrantRequest > requestReactiveOAuth2AccessTokenResponseClient () {
755
+ return this .tokenResponseClient ;
756
+ }
757
+
758
+ }
759
+
677
760
@ Configuration
678
761
@ EnableWebFluxSecurity
679
762
static class OAuth2LoginWithMultipleClientRegistrations {
0 commit comments