瀏覽代碼

Allow custom OAuth2ErrorHttpMessageConverter with OAuth2ErrorResponseErrorHandler

Closes gh-10425
Khaled Hamlaoui 3 年之前
父節點
當前提交
498636e26b

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

@@ -23,10 +23,12 @@ import com.nimbusds.oauth2.sdk.token.BearerTokenError;
 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;
@@ -41,7 +43,7 @@ import org.springframework.web.client.ResponseErrorHandler;
  */
 public class OAuth2ErrorResponseErrorHandler implements ResponseErrorHandler {
 
-	private final OAuth2ErrorHttpMessageConverter oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter();
+	private HttpMessageConverter<OAuth2Error> oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter();
 
 	private final ResponseErrorHandler defaultErrorHandler = new DefaultResponseErrorHandler();
 
@@ -89,4 +91,15 @@ public class OAuth2ErrorResponseErrorHandler implements ResponseErrorHandler {
 		}
 	}
 
+	/**
+	 * 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;
+	}
+
 }

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

@@ -23,12 +23,19 @@ import org.junit.jupiter.api.Test;
 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}.
@@ -53,6 +60,26 @@ public class OAuth2ErrorResponseErrorHandlerTests {
 				.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\"";