1
1
/*
2
- * Copyright 2002-2018 the original author or authors.
2
+ * Copyright 2002-2019 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
15
15
*/
16
16
package org .springframework .security .config .annotation .web .configuration ;
17
17
18
+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
19
+ import static org .mockito .ArgumentMatchers .any ;
20
+ import static org .mockito .ArgumentMatchers .eq ;
21
+ import static org .mockito .Mockito .mock ;
22
+ import static org .mockito .Mockito .times ;
23
+ import static org .mockito .Mockito .verify ;
24
+ import static org .mockito .Mockito .verifyZeroInteractions ;
25
+ import static org .mockito .Mockito .when ;
26
+ import static org .springframework .security .oauth2 .client .registration .TestClientRegistrations .clientCredentials ;
27
+ import static org .springframework .security .test .web .servlet .request .SecurityMockMvcRequestPostProcessors .authentication ;
28
+ import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .get ;
29
+ import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .content ;
30
+ import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .status ;
31
+
32
+ import javax .servlet .http .HttpServletRequest ;
18
33
import org .junit .Rule ;
19
34
import org .junit .Test ;
20
35
import org .springframework .beans .factory .NoSuchBeanDefinitionException ;
26
41
import org .springframework .security .config .test .SpringTestRule ;
27
42
import org .springframework .security .oauth2 .client .OAuth2AuthorizedClient ;
28
43
import org .springframework .security .oauth2 .client .annotation .RegisteredOAuth2AuthorizedClient ;
44
+ import org .springframework .security .oauth2 .client .endpoint .OAuth2AccessTokenResponseClient ;
45
+ import org .springframework .security .oauth2 .client .endpoint .OAuth2ClientCredentialsGrantRequest ;
46
+ import org .springframework .security .oauth2 .client .registration .ClientRegistration ;
29
47
import org .springframework .security .oauth2 .client .registration .ClientRegistrationRepository ;
30
48
import org .springframework .security .oauth2 .client .web .OAuth2AuthorizedClientRepository ;
31
49
import org .springframework .security .oauth2 .core .OAuth2AccessToken ;
50
+ import org .springframework .security .oauth2 .core .endpoint .OAuth2AccessTokenResponse ;
32
51
import org .springframework .test .web .servlet .MockMvc ;
33
52
import org .springframework .web .bind .annotation .GetMapping ;
34
53
import org .springframework .web .bind .annotation .RestController ;
35
54
import org .springframework .web .servlet .config .annotation .EnableWebMvc ;
36
55
37
- import javax .servlet .http .HttpServletRequest ;
38
-
39
- import static org .assertj .core .api .Assertions .assertThatThrownBy ;
40
- import static org .mockito .ArgumentMatchers .any ;
41
- import static org .mockito .ArgumentMatchers .eq ;
42
- import static org .mockito .Mockito .mock ;
43
- import static org .mockito .Mockito .when ;
44
- import static org .springframework .security .test .web .servlet .request .SecurityMockMvcRequestPostProcessors .authentication ;
45
- import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .get ;
46
- import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .content ;
47
- import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .status ;
48
-
49
56
/**
50
57
* Tests for {@link OAuth2ClientConfiguration}.
51
58
*
@@ -64,26 +71,66 @@ public void requestWhenAuthorizedClientFoundThenMethodArgumentResolved() throws
64
71
String principalName = "user1" ;
65
72
TestingAuthenticationToken authentication = new TestingAuthenticationToken (principalName , "password" );
66
73
74
+ ClientRegistrationRepository clientRegistrationRepository = mock (ClientRegistrationRepository .class );
67
75
OAuth2AuthorizedClientRepository authorizedClientRepository = mock (OAuth2AuthorizedClientRepository .class );
68
76
OAuth2AuthorizedClient authorizedClient = mock (OAuth2AuthorizedClient .class );
69
77
when (authorizedClientRepository .loadAuthorizedClient (
70
- eq (clientRegistrationId ), eq (authentication ), any (HttpServletRequest .class ))).thenReturn (authorizedClient );
78
+ eq (clientRegistrationId ), eq (authentication ), any (HttpServletRequest .class )))
79
+ .thenReturn (authorizedClient );
71
80
72
81
OAuth2AccessToken accessToken = mock (OAuth2AccessToken .class );
73
82
when (authorizedClient .getAccessToken ()).thenReturn (accessToken );
74
83
84
+ OAuth2AccessTokenResponseClient accessTokenResponseClient = mock (OAuth2AccessTokenResponseClient .class );
85
+
86
+ OAuth2AuthorizedClientArgumentResolverConfig .CLIENT_REGISTRATION_REPOSITORY = clientRegistrationRepository ;
75
87
OAuth2AuthorizedClientArgumentResolverConfig .AUTHORIZED_CLIENT_REPOSITORY = authorizedClientRepository ;
88
+ OAuth2AuthorizedClientArgumentResolverConfig .ACCESS_TOKEN_RESPONSE_CLIENT = accessTokenResponseClient ;
76
89
this .spring .register (OAuth2AuthorizedClientArgumentResolverConfig .class ).autowire ();
77
90
78
91
this .mockMvc .perform (get ("/authorized-client" ).with (authentication (authentication )))
79
- .andExpect (status ().isOk ())
80
- .andExpect (content ().string ("resolved" ));
92
+ .andExpect (status ().isOk ())
93
+ .andExpect (content ().string ("resolved" ));
94
+ verifyZeroInteractions (accessTokenResponseClient );
95
+ }
96
+
97
+ @ Test
98
+ public void requestWhenAuthorizedClientNotFoundAndClientCredentialsThenTokenResponseClientIsUsed () throws Exception {
99
+ String clientRegistrationId = "client1" ;
100
+ String principalName = "user1" ;
101
+ TestingAuthenticationToken authentication = new TestingAuthenticationToken (principalName , "password" );
102
+
103
+ ClientRegistrationRepository clientRegistrationRepository = mock (ClientRegistrationRepository .class );
104
+ OAuth2AuthorizedClientRepository authorizedClientRepository = mock (OAuth2AuthorizedClientRepository .class );
105
+ OAuth2AccessTokenResponseClient accessTokenResponseClient = mock (OAuth2AccessTokenResponseClient .class );
106
+
107
+ ClientRegistration clientRegistration = clientCredentials ().registrationId (clientRegistrationId ).build ();
108
+ when (clientRegistrationRepository .findByRegistrationId (clientRegistrationId )).thenReturn (clientRegistration );
109
+
110
+ OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse .withToken ("access-token-1234" )
111
+ .tokenType (OAuth2AccessToken .TokenType .BEARER )
112
+ .expiresIn (300 )
113
+ .build ();
114
+ when (accessTokenResponseClient .getTokenResponse (any (OAuth2ClientCredentialsGrantRequest .class )))
115
+ .thenReturn (accessTokenResponse );
116
+
117
+ OAuth2AuthorizedClientArgumentResolverConfig .CLIENT_REGISTRATION_REPOSITORY = clientRegistrationRepository ;
118
+ OAuth2AuthorizedClientArgumentResolverConfig .AUTHORIZED_CLIENT_REPOSITORY = authorizedClientRepository ;
119
+ OAuth2AuthorizedClientArgumentResolverConfig .ACCESS_TOKEN_RESPONSE_CLIENT = accessTokenResponseClient ;
120
+ this .spring .register (OAuth2AuthorizedClientArgumentResolverConfig .class ).autowire ();
121
+
122
+ this .mockMvc .perform (get ("/authorized-client" ).with (authentication (authentication )))
123
+ .andExpect (status ().isOk ())
124
+ .andExpect (content ().string ("resolved" ));
125
+ verify (accessTokenResponseClient , times (1 )).getTokenResponse (any (OAuth2ClientCredentialsGrantRequest .class ));
81
126
}
82
127
83
128
@ EnableWebMvc
84
129
@ EnableWebSecurity
85
130
static class OAuth2AuthorizedClientArgumentResolverConfig extends WebSecurityConfigurerAdapter {
131
+ static ClientRegistrationRepository CLIENT_REGISTRATION_REPOSITORY ;
86
132
static OAuth2AuthorizedClientRepository AUTHORIZED_CLIENT_REPOSITORY ;
133
+ static OAuth2AccessTokenResponseClient <OAuth2ClientCredentialsGrantRequest > ACCESS_TOKEN_RESPONSE_CLIENT ;
87
134
88
135
@ Override
89
136
protected void configure (HttpSecurity http ) throws Exception {
@@ -100,13 +147,18 @@ public String authorizedClient(@RegisteredOAuth2AuthorizedClient("client1") OAut
100
147
101
148
@ Bean
102
149
public ClientRegistrationRepository clientRegistrationRepository () {
103
- return mock ( ClientRegistrationRepository . class ) ;
150
+ return CLIENT_REGISTRATION_REPOSITORY ;
104
151
}
105
152
106
153
@ Bean
107
154
public OAuth2AuthorizedClientRepository authorizedClientRepository () {
108
155
return AUTHORIZED_CLIENT_REPOSITORY ;
109
156
}
157
+
158
+ @ Bean
159
+ public OAuth2AccessTokenResponseClient <OAuth2ClientCredentialsGrantRequest > accessTokenResponseClient () {
160
+ return ACCESS_TOKEN_RESPONSE_CLIENT ;
161
+ }
110
162
}
111
163
112
164
// gh-5321
@@ -147,6 +199,11 @@ public OAuth2AuthorizedClientRepository authorizedClientRepository1() {
147
199
public OAuth2AuthorizedClientRepository authorizedClientRepository2 () {
148
200
return mock (OAuth2AuthorizedClientRepository .class );
149
201
}
202
+
203
+ @ Bean
204
+ public OAuth2AccessTokenResponseClient <OAuth2ClientCredentialsGrantRequest > accessTokenResponseClient () {
205
+ return mock (OAuth2AccessTokenResponseClient .class );
206
+ }
150
207
}
151
208
152
209
@ Test
@@ -208,5 +265,53 @@ public ClientRegistrationRepository clientRegistrationRepository2() {
208
265
public OAuth2AuthorizedClientRepository authorizedClientRepository () {
209
266
return mock (OAuth2AuthorizedClientRepository .class );
210
267
}
268
+
269
+ @ Bean
270
+ public OAuth2AccessTokenResponseClient <OAuth2ClientCredentialsGrantRequest > accessTokenResponseClient () {
271
+ return mock (OAuth2AccessTokenResponseClient .class );
272
+ }
273
+ }
274
+
275
+ @ Test
276
+ public void loadContextWhenAccessTokenResponseClientRegisteredTwiceThenThrowNoUniqueBeanDefinitionException () {
277
+ assertThatThrownBy (() -> this .spring .register (AccessTokenResponseClientRegisteredTwiceConfig .class ).autowire ())
278
+ .hasRootCauseInstanceOf (NoUniqueBeanDefinitionException .class )
279
+ .hasMessageContaining ("expected single matching bean but found 2: accessTokenResponseClient1,accessTokenResponseClient2" );
280
+ }
281
+
282
+ @ EnableWebMvc
283
+ @ EnableWebSecurity
284
+ static class AccessTokenResponseClientRegisteredTwiceConfig extends WebSecurityConfigurerAdapter {
285
+
286
+ @ Override
287
+ protected void configure (HttpSecurity http ) throws Exception {
288
+ // @formatter:off
289
+ http
290
+ .authorizeRequests ()
291
+ .anyRequest ().authenticated ()
292
+ .and ()
293
+ .oauth2Login ();
294
+ // @formatter:on
295
+ }
296
+
297
+ @ Bean
298
+ public ClientRegistrationRepository clientRegistrationRepository () {
299
+ return mock (ClientRegistrationRepository .class );
300
+ }
301
+
302
+ @ Bean
303
+ public OAuth2AuthorizedClientRepository authorizedClientRepository () {
304
+ return mock (OAuth2AuthorizedClientRepository .class );
305
+ }
306
+
307
+ @ Bean
308
+ public OAuth2AccessTokenResponseClient <OAuth2ClientCredentialsGrantRequest > accessTokenResponseClient1 () {
309
+ return mock (OAuth2AccessTokenResponseClient .class );
310
+ }
311
+
312
+ @ Bean
313
+ public OAuth2AccessTokenResponseClient <OAuth2ClientCredentialsGrantRequest > accessTokenResponseClient2 () {
314
+ return mock (OAuth2AccessTokenResponseClient .class );
315
+ }
211
316
}
212
317
}
0 commit comments