Skip to content

Commit 75a2c2b

Browse files
raphaelDLrwinch
authored andcommitted
OAuth2AccessTokenResponseBodyExtractor supports Object values
This commit ensures the token response is parsed correctly if the values are not a String. Fixes: gh-6087
1 parent 808fbfa commit 75a2c2b

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ class OAuth2AccessTokenResponseBodyExtractor
5555
@Override
5656
public Mono<OAuth2AccessTokenResponse> extract(ReactiveHttpInputMessage inputMessage,
5757
Context context) {
58-
ParameterizedTypeReference<Map<String, String>> type = new ParameterizedTypeReference<Map<String, String>>() {};
59-
BodyExtractor<Mono<Map<String, String>>, ReactiveHttpInputMessage> delegate = BodyExtractors.toMono(type);
58+
ParameterizedTypeReference<Map<String, Object>> type = new ParameterizedTypeReference<Map<String, Object>>() {};
59+
BodyExtractor<Mono<Map<String, Object>>, ReactiveHttpInputMessage> delegate = BodyExtractors.toMono(type);
6060
return delegate.extract(inputMessage, context)
61-
.map(json -> parse(json))
61+
.map(OAuth2AccessTokenResponseBodyExtractor::parse)
6262
.flatMap(OAuth2AccessTokenResponseBodyExtractor::oauth2AccessTokenResponse)
6363
.map(OAuth2AccessTokenResponseBodyExtractor::oauth2AccessTokenResponse);
6464
}
6565

66-
private static TokenResponse parse(Map<String, String> json) {
66+
private static TokenResponse parse(Map<String, Object> json) {
6767
try {
6868
return TokenResponse.parse(new JSONObject(json));
6969
}

oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractorsTests.java

+29
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,33 @@ public void oauth2AccessTokenResponseWhenValidThenCreated() throws Exception {
120120
assertThat(result.getRefreshToken().getTokenValue()).isEqualTo("tGzv3JOkF0XG5Qx2TlKWIA");
121121
assertThat(result.getAdditionalParameters()).containsEntry("example_parameter", "example_value");
122122
}
123+
124+
125+
@Test
126+
// gh-6087
127+
public void oauth2AccessTokenResponseWhenMultipleAttributeTypesThenCreated() throws Exception {
128+
BodyExtractor<Mono<OAuth2AccessTokenResponse>, ReactiveHttpInputMessage> extractor = OAuth2BodyExtractors
129+
.oauth2AccessTokenResponse();
130+
131+
MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK);
132+
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
133+
response.setBody("{\n"
134+
+ " \"access_token\":\"2YotnFZFEjr1zCsicMWpAA\",\n"
135+
+ " \"token_type\":\"Bearer\",\n"
136+
+ " \"expires_in\":3600,\n"
137+
+ " \"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\",\n"
138+
+ " \"subjson\":{}, \n"
139+
+ " \"list\":[] \n"
140+
+ " }");
141+
142+
Instant now = Instant.now();
143+
OAuth2AccessTokenResponse result = extractor.extract(response, this.context).block();
144+
145+
assertThat(result.getAccessToken().getTokenValue()).isEqualTo("2YotnFZFEjr1zCsicMWpAA");
146+
assertThat(result.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER);
147+
assertThat(result.getAccessToken().getExpiresAt()).isBetween(now.plusSeconds(3600), now.plusSeconds(3600 + 2));
148+
assertThat(result.getRefreshToken().getTokenValue()).isEqualTo("tGzv3JOkF0XG5Qx2TlKWIA");
149+
assertThat(result.getAdditionalParameters().get("subjson")).isInstanceOfAny(Map.class);
150+
assertThat(result.getAdditionalParameters().get("list")).isInstanceOfAny(List.class);
151+
}
123152
}

0 commit comments

Comments
 (0)