Skip to content

Commit 498636e

Browse files
karhoo-renaultsjohnr
authored andcommitted
Allow custom OAuth2ErrorHttpMessageConverter with OAuth2ErrorResponseErrorHandler
Closes gh-10425
1 parent bd34d70 commit 498636e

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandler.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
import org.springframework.http.HttpHeaders;
2424
import org.springframework.http.HttpStatus;
2525
import org.springframework.http.client.ClientHttpResponse;
26+
import org.springframework.http.converter.HttpMessageConverter;
2627
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
2728
import org.springframework.security.oauth2.core.OAuth2Error;
2829
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
2930
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
31+
import org.springframework.util.Assert;
3032
import org.springframework.util.StringUtils;
3133
import org.springframework.web.client.DefaultResponseErrorHandler;
3234
import org.springframework.web.client.ResponseErrorHandler;
@@ -41,7 +43,7 @@
4143
*/
4244
public class OAuth2ErrorResponseErrorHandler implements ResponseErrorHandler {
4345

44-
private final OAuth2ErrorHttpMessageConverter oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter();
46+
private HttpMessageConverter<OAuth2Error> oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter();
4547

4648
private final ResponseErrorHandler defaultErrorHandler = new DefaultResponseErrorHandler();
4749

@@ -89,4 +91,15 @@ private BearerTokenError getBearerToken(String wwwAuthenticateHeader) {
8991
}
9092
}
9193

94+
/**
95+
* Sets the {@link HttpMessageConverter} for an OAuth 2.0 Error.
96+
* @param oauth2ErrorConverter A {@link HttpMessageConverter} for an
97+
* {@link OAuth2Error OAuth 2.0 Error}.
98+
* @since 5.7
99+
*/
100+
public final void setErrorConverter(HttpMessageConverter<OAuth2Error> oauth2ErrorConverter) {
101+
Assert.notNull(oauth2ErrorConverter, "oauth2ErrorConverter cannot be null");
102+
this.oauth2ErrorConverter = oauth2ErrorConverter;
103+
}
104+
92105
}

oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandlerTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@
2323
import org.springframework.http.HttpHeaders;
2424
import org.springframework.http.HttpStatus;
2525
import org.springframework.http.client.ClientHttpResponse;
26+
import org.springframework.http.converter.HttpMessageConverter;
2627
import org.springframework.mock.http.MockHttpInputMessage;
2728
import org.springframework.mock.http.client.MockClientHttpResponse;
2829
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
30+
import org.springframework.security.oauth2.core.OAuth2Error;
2931
import org.springframework.web.client.UnknownHttpStatusCodeException;
3032

3133
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
34+
import static org.mockito.ArgumentMatchers.any;
35+
import static org.mockito.ArgumentMatchers.eq;
36+
import static org.mockito.BDDMockito.given;
37+
import static org.mockito.Mockito.mock;
38+
import static org.mockito.Mockito.verify;
3239

3340
/**
3441
* Tests for {@link OAuth2ErrorResponseErrorHandler}.
@@ -53,6 +60,26 @@ public void handleErrorWhenErrorResponseBodyThenHandled() {
5360
.withMessage("[unauthorized_client] The client is not authorized");
5461
}
5562

63+
@Test
64+
public void handleErrorWhenOAuth2ErrorConverterSetThenCalled() throws IOException {
65+
HttpMessageConverter<OAuth2Error> oauth2ErrorConverter = mock(HttpMessageConverter.class);
66+
this.errorHandler.setErrorConverter(oauth2ErrorConverter);
67+
// @formatter:off
68+
String errorResponse = "{\n"
69+
+ " \"errorCode\": \"unauthorized_client\",\n"
70+
+ " \"errorSummary\": \"The client is not authorized\"\n"
71+
+ "}\n";
72+
// @formatter:on
73+
MockClientHttpResponse response = new MockClientHttpResponse(errorResponse.getBytes(), HttpStatus.BAD_REQUEST);
74+
given(oauth2ErrorConverter.read(any(), any()))
75+
.willReturn(new OAuth2Error("unauthorized_client", "The client is not authorized", null));
76+
77+
assertThatExceptionOfType(OAuth2AuthorizationException.class)
78+
.isThrownBy(() -> this.errorHandler.handleError(response))
79+
.withMessage("[unauthorized_client] The client is not authorized");
80+
verify(oauth2ErrorConverter).read(eq(OAuth2Error.class), eq(response));
81+
}
82+
5683
@Test
5784
public void handleErrorWhenErrorResponseWwwAuthenticateHeaderThenHandled() {
5885
String wwwAuthenticateHeader = "Bearer realm=\"auth-realm\" error=\"insufficient_scope\" error_description=\"The access token expired\"";

0 commit comments

Comments
 (0)