Skip to content

Commit 47df1ba

Browse files
committed
Polish tests spring-projectsgh-128
1 parent 1477fdc commit 47df1ba

File tree

10 files changed

+401
-349
lines changed

10 files changed

+401
-349
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.springframework.security.authentication.AuthenticationProvider;
1919
import org.springframework.security.core.Authentication;
2020
import org.springframework.security.core.AuthenticationException;
21+
import org.springframework.security.oauth2.core.AuthorizationGrantType;
2122
import org.springframework.security.oauth2.core.OAuth2AccessToken;
2223
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2324
import org.springframework.security.oauth2.core.OAuth2Error;
@@ -91,6 +92,10 @@ public Authentication authenticate(Authentication authentication) throws Authent
9192
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT));
9293
}
9394

95+
if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN)) {
96+
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT));
97+
}
98+
9499
Instant refreshTokenExpiresAt = authorization.getTokens().getRefreshToken().getExpiresAt();
95100
if (refreshTokenExpiresAt.isBefore(Instant.now())) {
96101
// As per https://tools.ietf.org/html/rfc6749#section-5.2
@@ -125,7 +130,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
125130
}
126131

127132
authorization = OAuth2Authorization.from(authorization)
128-
.tokens(OAuth2Tokens.builder().accessToken(accessToken).refreshToken(refreshToken).build())
133+
.tokens(OAuth2Tokens.from(authorization.getTokens()).accessToken(accessToken).refreshToken(refreshToken).build())
129134
.attribute(OAuth2AuthorizationAttributeNames.ACCESS_TOKEN_ATTRIBUTES, jwt)
130135
.build();
131136
this.authorizationService.save(authorization);

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public void requestWhenAuthorizationRequestAuthenticatedThenRedirectToClient() t
144144
}
145145

146146
@Test
147-
public void requestWhenTokenRequestValidThenResponseIncludesCacheHeaders() throws Exception {
147+
public void requestWhenTokenRequestValidThenReturnAccessTokenResponse() throws Exception {
148148
this.spring.register(AuthorizationServerConfiguration.class).autowire();
149149

150150
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
@@ -157,13 +157,18 @@ public void requestWhenTokenRequestValidThenResponseIncludesCacheHeaders() throw
157157
eq(TokenType.AUTHORIZATION_CODE)))
158158
.thenReturn(authorization);
159159

160-
this.mvc.perform(MockMvcRequestBuilders.post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
160+
this.mvc.perform(post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
161161
.params(getTokenRequestParameters(registeredClient, authorization))
162162
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
163163
registeredClient.getClientId(), registeredClient.getClientSecret())))
164164
.andExpect(status().isOk())
165165
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
166-
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")));
166+
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
167+
.andExpect(jsonPath("$.access_token").isNotEmpty())
168+
.andExpect(jsonPath("$.token_type").isNotEmpty())
169+
.andExpect(jsonPath("$.expires_in").isNotEmpty())
170+
.andExpect(jsonPath("$.refresh_token").isNotEmpty())
171+
.andExpect(jsonPath("$.scope").isNotEmpty());
167172

168173
verify(registeredClientRepository).findByClientId(eq(registeredClient.getClientId()));
169174
verify(authorizationService).findByToken(
@@ -173,12 +178,13 @@ public void requestWhenTokenRequestValidThenResponseIncludesCacheHeaders() throw
173178
}
174179

175180
@Test
176-
public void requestWhenPublicClientWithPkceThenReturnAccessToken() throws Exception {
181+
public void requestWhenPublicClientWithPkceThenReturnAccessTokenResponse() throws Exception {
177182
this.spring.register(AuthorizationServerConfiguration.class).autowire();
178183

179184
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
180185
.clientSecret(null)
181186
.clientSettings(clientSettings -> clientSettings.requireProofKey(true))
187+
.tokenSettings(tokenSettings -> tokenSettings.enableRefreshTokens(false))
182188
.build();
183189
when(registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
184190
.thenReturn(registeredClient);
@@ -208,7 +214,11 @@ public void requestWhenPublicClientWithPkceThenReturnAccessToken() throws Except
208214
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
209215
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
210216
.andExpect(status().isOk())
211-
.andExpect(jsonPath("$.access_token").isNotEmpty());
217+
.andExpect(jsonPath("$.access_token").isNotEmpty())
218+
.andExpect(jsonPath("$.token_type").isNotEmpty())
219+
.andExpect(jsonPath("$.expires_in").isNotEmpty())
220+
.andExpect(jsonPath("$.refresh_token").doesNotExist())
221+
.andExpect(jsonPath("$.scope").isNotEmpty());
212222

213223
verify(registeredClientRepository, times(2)).findByClientId(eq(registeredClient.getClientId()));
214224
verify(authorizationService, times(2)).findByToken(
@@ -217,46 +227,6 @@ public void requestWhenPublicClientWithPkceThenReturnAccessToken() throws Except
217227
verify(authorizationService, times(2)).save(any());
218228
}
219229

220-
@Test
221-
public void requestWhenPublicClientWithRefreshThenReturnRefreshToken() throws Exception {
222-
this.spring.register(AuthorizationServerConfiguration.class).autowire();
223-
224-
RegisteredClient registeredClient = TestRegisteredClients
225-
.registeredClient()
226-
.clientSecret(null)
227-
.tokenSettings(tokenSettings -> tokenSettings.enableRefreshTokens(true))
228-
.build();
229-
when(registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
230-
.thenReturn(registeredClient);
231-
232-
MvcResult mvcResult = this.mvc.perform(get(OAuth2AuthorizationEndpointFilter.DEFAULT_AUTHORIZATION_ENDPOINT_URI)
233-
.params(getAuthorizationRequestParameters(registeredClient))
234-
.param(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
235-
.param(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
236-
.with(user("user")))
237-
.andExpect(status().is3xxRedirection())
238-
.andReturn();
239-
assertThat(mvcResult.getResponse().getRedirectedUrl()).matches("https://example.com\\?code=.{15,}&state=state");
240-
241-
verify(registeredClientRepository).findByClientId(eq(registeredClient.getClientId()));
242-
243-
ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
244-
verify(authorizationService).save(authorizationCaptor.capture());
245-
OAuth2Authorization authorization = authorizationCaptor.getValue();
246-
247-
when(authorizationService.findByToken(
248-
eq(authorization.getTokens().getToken(OAuth2AuthorizationCode.class).getTokenValue()),
249-
eq(TokenType.AUTHORIZATION_CODE)))
250-
.thenReturn(authorization);
251-
252-
this.mvc.perform(post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
253-
.params(getTokenRequestParameters(registeredClient, authorization))
254-
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
255-
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
256-
.andExpect(status().isOk())
257-
.andExpect(jsonPath("$.refresh_token").isNotEmpty());
258-
}
259-
260230
private static MultiValueMap<String, String> getAuthorizationRequestParameters(RegisteredClient registeredClient) {
261231
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
262232
parameters.set(OAuth2ParameterNames.RESPONSE_TYPE, OAuth2AuthorizationResponseType.CODE.getValue());

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2RefreshTokenGrantTests.java

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,22 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
1817

19-
import java.time.Instant;
20-
2118
import org.junit.Before;
2219
import org.junit.BeforeClass;
2320
import org.junit.Rule;
2421
import org.junit.Test;
25-
2622
import org.springframework.beans.factory.annotation.Autowired;
2723
import org.springframework.context.annotation.Bean;
2824
import org.springframework.context.annotation.Import;
25+
import org.springframework.http.HttpHeaders;
2926
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
3027
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
3128
import org.springframework.security.config.test.SpringTestRule;
3229
import org.springframework.security.crypto.keys.KeyManager;
3330
import org.springframework.security.crypto.keys.StaticKeyGeneratingKeyManager;
3431
import org.springframework.security.oauth2.core.AuthorizationGrantType;
35-
import org.springframework.security.oauth2.core.OAuth2AccessToken;
36-
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
3732
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
3833
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
3934
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
@@ -42,27 +37,34 @@
4237
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
4338
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
4439
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
45-
import org.springframework.security.oauth2.server.authorization.token.OAuth2Tokens;
4640
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
4741
import org.springframework.test.web.servlet.MockMvc;
42+
import org.springframework.util.LinkedMultiValueMap;
43+
import org.springframework.util.MultiValueMap;
4844

45+
import java.net.URLEncoder;
46+
import java.nio.charset.StandardCharsets;
47+
import java.util.Base64;
48+
49+
import static org.hamcrest.CoreMatchers.containsString;
50+
import static org.mockito.ArgumentMatchers.any;
4951
import static org.mockito.ArgumentMatchers.eq;
5052
import static org.mockito.Mockito.mock;
5153
import static org.mockito.Mockito.reset;
54+
import static org.mockito.Mockito.verify;
5255
import static org.mockito.Mockito.when;
53-
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
5456
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
57+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
5558
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
5659
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
5760

5861
/**
62+
* Integration tests for the OAuth 2.0 Refresh Token Grant.
63+
*
5964
* @author Alexey Nesterov
6065
* @since 0.0.3
6166
*/
6267
public class OAuth2RefreshTokenGrantTests {
63-
64-
private static final String TEST_REFRESH_TOKEN = "test-refresh-token";
65-
6668
private static RegisteredClientRepository registeredClientRepository;
6769
private static OAuth2AuthorizationService authorizationService;
6870

@@ -72,8 +74,6 @@ public class OAuth2RefreshTokenGrantTests {
7274
@Autowired
7375
private MockMvc mvc;
7476

75-
private RegisteredClient registeredClient;
76-
7777
@BeforeClass
7878
public static void init() {
7979
registeredClientRepository = mock(RegisteredClientRepository.class);
@@ -84,33 +84,56 @@ public static void init() {
8484
public void setup() {
8585
reset(registeredClientRepository);
8686
reset(authorizationService);
87-
88-
this.registeredClient = TestRegisteredClients.registeredClient2().build();
89-
90-
this.spring.register(OAuth2RefreshTokenGrantTests.AuthorizationServerConfiguration.class).autowire();
9187
}
9288

9389
@Test
94-
public void requestWhenRefreshTokenExists() throws Exception {
95-
when(registeredClientRepository.findByClientId(eq(this.registeredClient.getClientId())))
96-
.thenReturn(this.registeredClient);
97-
98-
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient)
99-
.tokens(OAuth2Tokens.builder()
100-
.refreshToken(new OAuth2RefreshToken(TEST_REFRESH_TOKEN, Instant.now(), Instant.now().plusSeconds(60)))
101-
.accessToken(new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", Instant.now(), Instant.now().plusSeconds(10)))
102-
.build())
103-
.build();
104-
105-
when(authorizationService.findByToken(TEST_REFRESH_TOKEN, TokenType.REFRESH_TOKEN))
90+
public void requestWhenRefreshTokenRequestValidThenReturnAccessTokenResponse() throws Exception {
91+
this.spring.register(AuthorizationServerConfiguration.class).autowire();
92+
93+
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
94+
when(registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
95+
.thenReturn(registeredClient);
96+
97+
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
98+
when(authorizationService.findByToken(
99+
eq(authorization.getTokens().getRefreshToken().getTokenValue()),
100+
eq(TokenType.REFRESH_TOKEN)))
106101
.thenReturn(authorization);
107102

108103
this.mvc.perform(post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
109-
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.REFRESH_TOKEN.getValue())
110-
.param(OAuth2ParameterNames.REFRESH_TOKEN, TEST_REFRESH_TOKEN)
111-
.with(httpBasic(this.registeredClient.getClientId(), this.registeredClient.getClientSecret())))
104+
.params(getRefreshTokenRequestParameters(authorization))
105+
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
106+
registeredClient.getClientId(), registeredClient.getClientSecret())))
112107
.andExpect(status().isOk())
113-
.andExpect(jsonPath("$.access_token").isNotEmpty());
108+
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
109+
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
110+
.andExpect(jsonPath("$.access_token").isNotEmpty())
111+
.andExpect(jsonPath("$.token_type").isNotEmpty())
112+
.andExpect(jsonPath("$.expires_in").isNotEmpty())
113+
.andExpect(jsonPath("$.refresh_token").isNotEmpty())
114+
.andExpect(jsonPath("$.scope").isNotEmpty());
115+
116+
verify(registeredClientRepository).findByClientId(eq(registeredClient.getClientId()));
117+
verify(authorizationService).findByToken(
118+
eq(authorization.getTokens().getRefreshToken().getTokenValue()),
119+
eq(TokenType.REFRESH_TOKEN));
120+
verify(authorizationService).save(any());
121+
122+
}
123+
124+
private static MultiValueMap<String, String> getRefreshTokenRequestParameters(OAuth2Authorization authorization) {
125+
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
126+
parameters.set(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.REFRESH_TOKEN.getValue());
127+
parameters.set(OAuth2ParameterNames.REFRESH_TOKEN, authorization.getTokens().getRefreshToken().getTokenValue());
128+
return parameters;
129+
}
130+
131+
private static String encodeBasicAuth(String clientId, String secret) throws Exception {
132+
clientId = URLEncoder.encode(clientId, StandardCharsets.UTF_8.name());
133+
secret = URLEncoder.encode(secret, StandardCharsets.UTF_8.name());
134+
String credentialsString = clientId + ":" + secret;
135+
byte[] encodedBytes = Base64.getEncoder().encode(credentialsString.getBytes(StandardCharsets.UTF_8));
136+
return new String(encodedBytes, StandardCharsets.UTF_8);
114137
}
115138

116139
@EnableWebSecurity

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/InMemoryOAuth2AuthorizationServiceTests.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,17 @@ public void findByTokenWhenTokenTypeAccessTokenThenFound() {
143143
}
144144

145145
@Test
146-
public void findByTokenAndTokenTypeWhenTokenTypeRefreshTokenThenFound() {
147-
final String refreshTokenValue = "refresh-token";
148-
OAuth2Authorization expectedAuthorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
149-
.principalName(PRINCIPAL_NAME)
150-
.tokens(OAuth2Tokens.builder().refreshToken(new OAuth2RefreshToken(refreshTokenValue, Instant.now().plusSeconds(10))).build())
151-
.build();
152-
this.authorizationService.save(expectedAuthorization);
146+
public void findByTokenWhenTokenTypeRefreshTokenThenFound() {
147+
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now());
148+
OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
149+
.principalName(PRINCIPAL_NAME)
150+
.tokens(OAuth2Tokens.builder().refreshToken(refreshToken).build())
151+
.build();
152+
this.authorizationService.save(authorization);
153153

154154
OAuth2Authorization result = this.authorizationService.findByToken(
155-
refreshTokenValue, TokenType.REFRESH_TOKEN);
156-
assertThat(result).isEqualTo(expectedAuthorization);
155+
refreshToken.getTokenValue(), TokenType.REFRESH_TOKEN);
156+
assertThat(authorization).isEqualTo(result);
157157
}
158158

159159
@Test

0 commit comments

Comments
 (0)