Skip to content

Commit fb2bbd7

Browse files
committed
OAuth2AccessTokenResponseHttpMessageConverter handles JSON object parameters
Fixes gh-6463
1 parent fa73b13 commit fb2bbd7

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.nio.charset.Charset;
1919
import java.nio.charset.StandardCharsets;
2020
import java.util.Map;
21+
import java.util.stream.Collectors;
2122

2223
import org.springframework.core.ParameterizedTypeReference;
2324
import org.springframework.core.convert.converter.Converter;
@@ -45,8 +46,8 @@
4546
public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpMessageConverter<OAuth2AccessTokenResponse> {
4647
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
4748

48-
private static final ParameterizedTypeReference<Map<String, String>> PARAMETERIZED_RESPONSE_TYPE =
49-
new ParameterizedTypeReference<Map<String, String>>() {};
49+
private static final ParameterizedTypeReference<Map<String, Object>> PARAMETERIZED_RESPONSE_TYPE =
50+
new ParameterizedTypeReference<Map<String, Object>>() {};
5051

5152
private GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter();
5253

@@ -70,10 +71,16 @@ protected OAuth2AccessTokenResponse readInternal(Class<? extends OAuth2AccessTok
7071
throws HttpMessageNotReadableException {
7172

7273
try {
74+
// gh-6463
75+
// Parse parameter values as Object in order to handle potential JSON Object and then convert values to String
7376
@SuppressWarnings("unchecked")
74-
Map<String, String> tokenResponseParameters = (Map<String, String>) this.jsonMessageConverter.read(
77+
Map<String, Object> tokenResponseParameters = (Map<String, Object>) this.jsonMessageConverter.read(
7578
PARAMETERIZED_RESPONSE_TYPE.getType(), null, inputMessage);
76-
return this.tokenResponseConverter.convert(tokenResponseParameters);
79+
return this.tokenResponseConverter.convert(
80+
tokenResponseParameters.entrySet().stream()
81+
.collect(Collectors.toMap(
82+
Map.Entry::getKey,
83+
entry -> entry.getValue().toString())));
7784
} catch (Exception ex) {
7885
throw new HttpMessageNotReadableException("An error occurred reading the OAuth 2.0 Access Token Response: " +
7986
ex.getMessage(), ex, inputMessage);

oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverterTests.java

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -96,6 +96,39 @@ public void readInternalWhenSuccessfulTokenResponseThenReadOAuth2AccessTokenResp
9696

9797
}
9898

99+
// gh-6463
100+
@Test
101+
public void readInternalWhenSuccessfulTokenResponseWithObjectThenReadOAuth2AccessTokenResponse() {
102+
String tokenResponse = "{\n" +
103+
" \"access_token\": \"access-token-1234\",\n" +
104+
" \"token_type\": \"bearer\",\n" +
105+
" \"expires_in\": 3600,\n" +
106+
" \"scope\": \"read write\",\n" +
107+
" \"refresh_token\": \"refresh-token-1234\",\n" +
108+
" \"custom_object_1\": {\"name1\": \"value1\"},\n" +
109+
" \"custom_object_2\": [\"value1\", \"value2\"],\n" +
110+
" \"custom_parameter_1\": \"custom-value-1\",\n" +
111+
" \"custom_parameter_2\": \"custom-value-2\"\n" +
112+
"}\n";
113+
114+
MockClientHttpResponse response = new MockClientHttpResponse(
115+
tokenResponse.getBytes(), HttpStatus.OK);
116+
117+
OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter.readInternal(
118+
OAuth2AccessTokenResponse.class, response);
119+
120+
assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234");
121+
assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
122+
assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBeforeOrEqualTo(Instant.now().plusSeconds(3600));
123+
assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read", "write");
124+
assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234");
125+
assertThat(accessTokenResponse.getAdditionalParameters()).containsExactly(
126+
entry("custom_object_1", "{name1=value1}"),
127+
entry("custom_object_2", "[value1, value2]"),
128+
entry("custom_parameter_1", "custom-value-1"),
129+
entry("custom_parameter_2", "custom-value-2"));
130+
}
131+
99132
@Test
100133
public void readInternalWhenConversionFailsThenThrowHttpMessageNotReadableException() {
101134
Converter tokenResponseConverter = mock(Converter.class);

0 commit comments

Comments
 (0)