Skip to content

Commit a377581

Browse files
committed
Fix WebClient Memory Leaks
WebClient exchange requires that the body is consumed. Before this commit there were places where an Exception was thrown without consuming the body if the status was not successful. There was also the potential for the statusCode invocation to throw an Exception of the status code was not defined which would cause a leak. This commit ensures that before the Exception is thrown the body is consumed. It also uses the http status in a way that will ensure an Exception is not thrown. Fixes gh-7293
1 parent 11f4235 commit a377581

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
*/
1616
package org.springframework.security.oauth2.client.endpoint;
1717

18+
import org.springframework.core.io.buffer.DataBuffer;
19+
import org.springframework.core.io.buffer.DataBufferUtils;
1820
import org.springframework.http.HttpHeaders;
21+
import org.springframework.http.HttpStatus;
1922
import org.springframework.http.MediaType;
2023
import org.springframework.security.oauth2.client.registration.ClientRegistration;
2124
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
@@ -66,15 +69,18 @@ public Mono<OAuth2AccessTokenResponse> getTokenResponse(OAuth2ClientCredentialsG
6669
.headers(headers(clientRegistration))
6770
.body(body)
6871
.exchange()
69-
.flatMap(response ->{
70-
if (!response.statusCode().is2xxSuccessful()){
72+
.flatMap(response -> {
73+
HttpStatus status = HttpStatus.resolve(response.rawStatusCode());
74+
if (status == null || !status.is2xxSuccessful()) {
7175
// extract the contents of this into a method named oauth2AccessTokenResponse but has an argument for the response
72-
throw WebClientResponseException.create(response.rawStatusCode(),
76+
return response.bodyToFlux(DataBuffer.class)
77+
.map(DataBufferUtils::release)
78+
.then(Mono.error(WebClientResponseException.create(response.rawStatusCode(),
7379
"Cannot get token, expected 2xx HTTP Status code",
7480
null,
7581
null,
7682
null
77-
);
83+
)));
7884
}
7985
return response.body(oauth2AccessTokenResponse()); })
8086
.map(response -> {

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
2929
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
3030
import com.nimbusds.oauth2.sdk.id.Audience;
31+
import org.springframework.core.io.buffer.DataBuffer;
32+
import org.springframework.core.io.buffer.DataBufferUtils;
3133
import reactor.core.publisher.Mono;
3234

3335
import org.springframework.http.HttpHeaders;
@@ -116,8 +118,10 @@ private Mono<HTTPResponse> adaptToNimbusResponse(ClientResponse responseEntity)
116118
HTTPResponse response = new HTTPResponse(responseEntity.rawStatusCode());
117119
response.setHeader(HttpHeaders.CONTENT_TYPE, responseEntity.headers().contentType().get().toString());
118120
if (response.getStatusCode() != HTTPResponse.SC_OK) {
119-
throw new OAuth2IntrospectionException(
120-
"Introspection endpoint responded with " + response.getStatusCode());
121+
return responseEntity.bodyToFlux(DataBuffer.class)
122+
.map(DataBufferUtils::release)
123+
.then(Mono.error(new OAuth2IntrospectionException(
124+
"Introspection endpoint responded with " + response.getStatusCode())));
121125
}
122126
return responseEntity.bodyToMono(String.class)
123127
.doOnNext(response::setContent)

0 commit comments

Comments
 (0)