From 93ed92cc948096c6831debe5b766e590c18e3da0 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 24 Mar 2020 14:43:49 -0400 Subject: [PATCH] OAuth2ErrorHttpMessageConverter handles JSON object parameters Fixes gh-8157 --- .../OAuth2ErrorHttpMessageConverter.java | 17 ++++++++++----- .../OAuth2ErrorHttpMessageConverterTests.java | 21 ++++++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java index 1e60804d80b..a9901c97d91 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; /** * A {@link HttpMessageConverter} for an {@link OAuth2Error OAuth 2.0 Error}. @@ -46,8 +47,8 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverter { private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = - new ParameterizedTypeReference>() {}; + private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = + new ParameterizedTypeReference>() {}; private GenericHttpMessageConverter jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter(); @@ -69,10 +70,16 @@ protected OAuth2Error readInternal(Class clazz, HttpInput throws HttpMessageNotReadableException { try { + // gh-8157 + // Parse parameter values as Object in order to handle potential JSON Object and then convert values to String @SuppressWarnings("unchecked") - Map errorParameters = (Map) this.jsonMessageConverter.read( + Map errorParameters = (Map) this.jsonMessageConverter.read( PARAMETERIZED_RESPONSE_TYPE.getType(), null, inputMessage); - return this.errorConverter.convert(errorParameters); + return this.errorConverter.convert( + errorParameters.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> String.valueOf(entry.getValue())))); } catch (Exception ex) { throw new HttpMessageNotReadableException("An error occurred reading the OAuth 2.0 Error: " + ex.getMessage(), ex, inputMessage); diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java index a57b1df1b83..11211aad561 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,6 +78,25 @@ public void readInternalWhenErrorResponseThenReadOAuth2Error() throws Exception assertThat(oauth2Error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6749#section-5.2"); } + // gh-8157 + @Test + public void readInternalWhenErrorResponseWithObjectThenReadOAuth2Error() throws Exception { + String errorResponse = "{\n" + + " \"error\": \"unauthorized_client\",\n" + + " \"error_description\": \"The client is not authorized\",\n" + + " \"error_codes\": [65001],\n" + + " \"error_uri\": \"https://tools.ietf.org/html/rfc6749#section-5.2\"\n" + + "}\n"; + + MockClientHttpResponse response = new MockClientHttpResponse( + errorResponse.getBytes(), HttpStatus.BAD_REQUEST); + + OAuth2Error oauth2Error = this.messageConverter.readInternal(OAuth2Error.class, response); + assertThat(oauth2Error.getErrorCode()).isEqualTo("unauthorized_client"); + assertThat(oauth2Error.getDescription()).isEqualTo("The client is not authorized"); + assertThat(oauth2Error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6749#section-5.2"); + } + @Test public void readInternalWhenConversionFailsThenThrowHttpMessageNotReadableException() { Converter errorConverter = mock(Converter.class);