Skip to content

Commit

Permalink
Allow custom OAuth2ErrorHttpMessageConverter with OAuth2ErrorResponse…
Browse files Browse the repository at this point in the history
…ErrorHandler

Closes spring-projectsgh-10425
  • Loading branch information
karhoo-renault authored and sjohnr committed Nov 16, 2021
1 parent bd34d70 commit 498636e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.ResponseErrorHandler;
Expand All @@ -41,7 +43,7 @@
*/
public class OAuth2ErrorResponseErrorHandler implements ResponseErrorHandler {

private final OAuth2ErrorHttpMessageConverter oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter();
private HttpMessageConverter<OAuth2Error> oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter();

private final ResponseErrorHandler defaultErrorHandler = new DefaultResponseErrorHandler();

Expand Down Expand Up @@ -89,4 +91,15 @@ private BearerTokenError getBearerToken(String wwwAuthenticateHeader) {
}
}

/**
* Sets the {@link HttpMessageConverter} for an OAuth 2.0 Error.
* @param oauth2ErrorConverter A {@link HttpMessageConverter} for an
* {@link OAuth2Error OAuth 2.0 Error}.
* @since 5.7
*/
public final void setErrorConverter(HttpMessageConverter<OAuth2Error> oauth2ErrorConverter) {
Assert.notNull(oauth2ErrorConverter, "oauth2ErrorConverter cannot be null");
this.oauth2ErrorConverter = oauth2ErrorConverter;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.mock.http.MockHttpInputMessage;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.web.client.UnknownHttpStatusCodeException;

import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

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

@Test
public void handleErrorWhenOAuth2ErrorConverterSetThenCalled() throws IOException {
HttpMessageConverter<OAuth2Error> oauth2ErrorConverter = mock(HttpMessageConverter.class);
this.errorHandler.setErrorConverter(oauth2ErrorConverter);
// @formatter:off
String errorResponse = "{\n"
+ " \"errorCode\": \"unauthorized_client\",\n"
+ " \"errorSummary\": \"The client is not authorized\"\n"
+ "}\n";
// @formatter:on
MockClientHttpResponse response = new MockClientHttpResponse(errorResponse.getBytes(), HttpStatus.BAD_REQUEST);
given(oauth2ErrorConverter.read(any(), any()))
.willReturn(new OAuth2Error("unauthorized_client", "The client is not authorized", null));

assertThatExceptionOfType(OAuth2AuthorizationException.class)
.isThrownBy(() -> this.errorHandler.handleError(response))
.withMessage("[unauthorized_client] The client is not authorized");
verify(oauth2ErrorConverter).read(eq(OAuth2Error.class), eq(response));
}

@Test
public void handleErrorWhenErrorResponseWwwAuthenticateHeaderThenHandled() {
String wwwAuthenticateHeader = "Bearer realm=\"auth-realm\" error=\"insufficient_scope\" error_description=\"The access token expired\"";
Expand Down

0 comments on commit 498636e

Please sign in to comment.