import java.util.LinkedList;
import java.util.List;
import javax.annotation.PostConstruct;
-import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
import org.springframework.security.oauth2.client.token.AccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
-import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@Autowired(required=false)
private List<AccessTokenProvider> accessTokenProviderChain;
- /**
- * Needed, to extract Jackson-ObjectMapper.
- * Defined by <mvc:annotation-driven />
- */
- @Autowired
- private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
-
- private ObjectMapper objectMapper;
@PostConstruct
public void init()
{
- for (HttpMessageConverter<?> messageConverter : requestMappingHandlerAdapter.getMessageConverters())
- {
- if (messageConverter instanceof MappingJacksonHttpMessageConverter)
- {
- MappingJacksonHttpMessageConverter m =
- (MappingJacksonHttpMessageConverter)messageConverter;
- objectMapper = m.getObjectMapper();
- log.info(
- "found ObjectMapper {} ({})",
- objectMapper,
- objectMapper.getClass().getCanonicalName()
- );
- break;
- }
- }
- if (objectMapper == null)
- {
- throw new RuntimeException(
- "Unable to find MappingJAcksonHttpMessageConverter!"
- );
- }
-
if (accessTokenProviderChain == null)
{
log.info("no AccessTokenProviderChain configured, creating default-chain");
SignedRequestAwareAuthorizationCodeAccessTokenProvider provider =
new SignedRequestAwareAuthorizationCodeAccessTokenProvider();
provider.setSecret(clientSecret);
- provider.setObjectMapper(objectMapper);
chain.add(provider);
template.setAccessTokenProvider(new AccessTokenProviderChain(chain));
log.info("injecting GraphApiErrorHandler");
package de.juplo.facebook;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
+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.http.converter.HttpMessageNotReadableException;
import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
+import org.springframework.util.FileCopyUtils;
import org.springframework.web.client.HttpMessageConverterExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@Override
public boolean hasError(ClientHttpResponse response) throws IOException
{
- return errorHandler.hasError(response);
+ return
+ HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())
+ || this.errorHandler.hasError(response);
}
@Override
- public void handleError(ClientHttpResponse response) throws IOException
+ public void handleError(final ClientHttpResponse response) throws IOException
{
- HttpMessageConverterExtractor<GraphApiException> extractor =
- new HttpMessageConverterExtractor<>(
- GraphApiException.class,
- messageConverters
- );
-
- try
+ if (!HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()))
{
- GraphApiException body = extractor.extractData(response);
- if (body != null)
- {
- // If we can get an OAuth2Exception already from the body, it is likely
- // to have more information than the header does, so just re-throw it
- // here.
- body.setHttpErrorCode(response.getRawStatusCode());
- throw body;
- }
+ // We should only care about 400 level errors. Ex: A 500 server error shouldn't
+ // be an oauth related error.
+ errorHandler.handleError(response);
}
- catch (RestClientException|HttpMessageNotReadableException e)
+ else
{
- // ignore
- }
+ // Need to use buffered response because input stream may need to be consumed multiple times.
+ ClientHttpResponse bufferedResponse = new ClientHttpResponse()
+ {
+ private byte[] lazyBody;
+
+ @Override
+ public HttpStatus getStatusCode() throws IOException
+ {
+ return response.getStatusCode();
+ }
+
+ @Override
+ public synchronized InputStream getBody() throws IOException
+ {
+ if (lazyBody == null) {
+ InputStream bodyStream = response.getBody();
+ if (bodyStream != null) {
+ lazyBody = FileCopyUtils.copyToByteArray(bodyStream);
+ }
+ else {
+ lazyBody = new byte[0];
+ }
+ }
+ return new ByteArrayInputStream(lazyBody);
+ }
+
+ @Override
+ public HttpHeaders getHeaders()
+ {
+ return response.getHeaders();
+ }
+
+ @Override
+ public String getStatusText() throws IOException
+ {
+ return response.getStatusText();
+ }
+
+ @Override
+ public void close()
+ {
+ response.close();
+ }
- errorHandler.handleError(response);
+ @Override
+ public int getRawStatusCode() throws IOException
+ {
+ return response.getRawStatusCode();
+ }
+ };
+
+
+ HttpMessageConverterExtractor<GraphApiException> extractor =
+ new HttpMessageConverterExtractor<>(
+ GraphApiException.class,
+ messageConverters
+ );
+
+ try
+ {
+ GraphApiException body = extractor.extractData(bufferedResponse);
+ if (body != null)
+ {
+ // If we can get an OAuth2Exception already from the body, it is likely
+ // to have more information than the header does, so just re-throw it
+ // here.
+ body.setHttpErrorCode(response.getRawStatusCode());
+ throw body;
+ }
+ }
+ catch (RestClientException|HttpMessageNotReadableException e)
+ {
+ // ignore
+ }
+
+ errorHandler.handleError(bufferedResponse);
+ }
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
-import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import static org.springframework.security.oauth2.common.OAuth2AccessToken.OAUTH2_TYPE;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
-import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.client.HttpClientErrorException;
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(OAuth2Exception e)
+ catch(HttpClientErrorException e)
{
log.debug("{}", e.toString());
- assertEquals("invalid_request", e.getOAuth2ErrorCode());
- assertFalse(e instanceof GraphApiException);
+ }
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
}
clientTemplate.getForObject("ANY", SOME.class);
fail("The expected exception was not thrown");
}
- catch(HttpMessageNotReadableException e)
+ catch(HttpClientErrorException e)
{
- // TODO: OAuth2ErrorHandler fails, if body contains no valid JSON!
log.debug("{}", e.toString());
}
+ catch(Exception e)
+ {
+ fail("A wrong exception was thrown: " + e.toString());
+ }
}