Q:

Spring social facebook unable to decode the information being sent from facebook access token URI

The code was working as expected around a week back and used to interpret the access tokens.  Now suddenly it started throwing exception:
org.springframework.social. MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization. 
    at org.springframework.social.facebook.api.impl. AbstractFacebookOperations.requireAuthorization(AbstractFacebookOperations.java:30)
    at org.springframework.social.facebook.api.impl. UserTemplate.getUserProfile(UserTemplate.java:48)
    at org.springframework.social.facebook.connect. FacebookAdapter.setConnectionValues(FacebookAdapter.java:42)
    at org.springframework.social.facebook.connect. FacebookAdapter.setConnectionValues(FacebookAdapter.java:30)
    at org.springframework.social.connect.support. AbstractConnection.setValues(AbstractConnection.java:174)
    at org.springframework.social.connect.support. AbstractConnection.initKey(AbstractConnection.java:137)
    at org.springframework.social.connect.support. OAuth2Connection.<init>(OAuth2Connection.java:75)
    at org.springframework.social.connect.support. OAuth2ConnectionFactory.createConnection(OAuth2ConnectionFactory.java:91)
    at org.springframework.social.security.provider. OAuth2AuthenticationService.getAuthToken(OAuth2AuthenticationService.java:99)
    at org.springframework.social.security. SocialAuthenticationFilter.attemptAuthService(SocialAuthenticationFilter.java:239)
    at org.springframework.social.security. SocialAuthenticationFilter.attemptAuthentication(SocialAuthenticationFilter.java:157)
    at org.springframework.security.web.authentication. AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
    at org.springframework.security.web. FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout. LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web. FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.csrf. CsrfFilter.doFilterInternal(CsrfFilter.java:85)
    at org.springframework.web.filter. OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web. FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header. HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter. OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web. FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context. SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web. FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async. WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter. OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web. FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web. FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web. FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.apache.catalina.core. ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core. ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.trace. WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:100)
    at org.springframework.web.filter. OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core. ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core. ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.autoconfigure. MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
    at org.springframework.web.filter. OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core. ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core. ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core. StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core. StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator. AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.valves. AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core. StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves. ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core. StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector. CoyoteAdapter.service(CoyoteAdapter.java:537)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
    at org.apache.coyote. AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net. NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
    at org.apache.tomcat.util.net. NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
    at java.util.concurrent. ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent. ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads. TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang. Thread.run(Unknown Source)

I tried to debug the code inside the libraries and found that the response being returned is not in the required format which needs to be interpreted by spring-social-facebook-1.1.1.RELEASE-sources.jar-> FacebookOAuth2Template-> postForAccessGrant().  In the below code snippet the access_token and expires needs to be taken with key value. 
@Override
    @SuppressWarnings("unchecked")  
    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
        MultiValueMap<String, String> response = getRestTemplate().postForObject(accessTokenUrl, parameters, MultiValueMap.class);
        String expires = response.getFirst("expires");
        return new AccessGrant(response.getFirst("access_token"), null, null, expires ! = null ?  Long.valueOf(expires) : null);
    }

The response returned from facebook graph access token API is:
{{"access_token":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","token_type":"bearer","expires_in":5157689}=[null]}

The line response.get is trying to retrieve these values from value field which is in this case null.  Hence it is setting accessToken and expiry values as null. 

A:

I have added below class as a temporary fix to the project which is overriding existing class from the library but this is not a proper solution.  Is there any fix which will solve this problem? 
package org.springframework.social.facebook.connect;

import java.io. IOException;
import java.util. Collections;
import java.util. HashMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j. LogManager;
import org.apache.log4j. Logger;
import org.codehaus.jackson.map. ObjectMapper;
import org.springframework.http. MediaType;
import org.springframework.http.converter. FormHttpMessageConverter;
import org.springframework.http.converter. HttpMessageConverter;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.social.support. ClientHttpRequestFactorySelector;
import org.springframework.util. MultiValueMap;
import org.springframework.web.client. RestTemplate;

public class FacebookOAuth2Template extends OAuth2Template {

    private static final Logger LOGGER = LogManager.getLogger(FacebookOAuth2Template.class);

    public FacebookOAuth2Template(String clientId, String clientSecret) {
        super(clientId, clientSecret, "https://www.facebook.com/v1.0/dialog/oauth", "https://graph.facebook.com/v1.0/oauth/access_token");
        setUseParametersForClientAuthentication(true);
    }

    @Override
    protected RestTemplate createRestTemplate() {
        RestTemplate restTemplate = new RestTemplate(ClientHttpRequestFactorySelector.getRequestFactory());
        FormHttpMessageConverter messageConverter = new FormHttpMessageConverter() {
            @Override
            public boolean canRead(Class<? > clazz, MediaType mediaType) {
                // always read as x-www-url-formencoded even though Facebook sets contentType to text/plain
                return true;
            }
        };
        restTemplate.setMessageConverters(Collections.<HttpMessageConverter<? >> singletonList(messageConverter));
        return restTemplate;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
        MultiValueMap<String, String> response = getRestTemplate().postForObject(accessTokenUrl, parameters, MultiValueMap.class);
        String expires = response.getFirst("expires");
        String accessToken = response.getFirst("access_token");
        if(!response.keySet().isEmpty() && (StringUtils.isEmpty(expires) || StringUtils.isEmpty(accessToken))) {
            for(String key : response.keySet()) {
                boolean valuesFound = false;
                HashMap<String, String> map;
                try {
                    //map = (HashMap<String, String>) JSONUtil.fromJSON(key, HashMap.class);
                    ObjectMapper objectMapper = new ObjectMapper();
                    map = objectMapper.readValue(key, HashMap.class);

                    if(StringUtils.isEmpty(expires)) {
                        expires = String.valueOf(map.get("expires_in"));
                        valuesFound = true;
                    }

                    if(StringUtils.isEmpty(accessToken)) {
                        accessToken = map.get("access_token");
                        valuesFound = true;
                    }

                    if(valuesFound) {
                        break;
                    }
                } catch(IOException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }
        return new AccessGrant(accessToken, null, null, expires ! = null ?  Long.valueOf(expires) : null);
    }
}

