Announcement Announcement Module
Collapse
No announcement yet.
Retrieving access code server side Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Retrieving access code server side

    Does the Spring Social Facebook provider support retrieving a access token via:
    graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&client_secret=Y OUR_APP_SECRET&grant_type=client_credentials

    I need to retrieve the access code this way as I want a backend server to connect with Facebook to execute various fql queries.

    This is also explained in server-side-login:
    http://developers.facebook.com/docs/...er-side-login/

    And is e.g. supported in fbrest library like: http://restfb.com/javadoc/com/restfb...va.lang.String, java.lang.String)


    I wonder if Spring Social Facebook supports this or that should create a feature request in jira?

  • #2
    It does support this in OAuth2Operations.authenticateClient(). (You don't have to pass in the client's credentials to this method, because they are already set on OAuth2Template at construction time.)

    Note that this is *NOT* integrated into the connection framework. In other words, there's no support for persisting this access token because the connection framework acts on behalf of the user but client credential authorization is acting on behalf of the application itself.

    The other thing to note is that this is a relatively new addition and is not part of Spring Social 1.0.x. It is available in 1.1.0.M1 and the latest snapshots, however.

    Comment


    • #3
      Hi Craig,

      Don't know if I can follow this completely. Should I create a OAuth2Template instead of a FacebookTemplate?
      How can I hook these up then? At end I need FacebookTemplate to have access to Graph operations.

      Note that the TwitterTemplate can be created with consumer key/secret and token/secret.
      I was looking for something similar with the FacebookTemplate.

      Note2: I'm on 1.1.0.M1 anyway so it's ok for me to use latest.

      Comment


      • #4
        Yes, you would create an OAuth2Template, use the authenticateClient() to get the access token (in an AccessGrant instance), then use the access token to construct a FacebookTemplate. Something like this:

        Code:
        OAuth2Template oauth = new OAuth2Template(clientId, clientSecret, "https://www.facebook.com/dialog/oauth", "https://graph.facebook.com/oauth/access_token");
        AccessGrant accessGrant = oauth.authenticateClient();
        FacebookTemplate facebook = new FacebookTemplate(accessGrant.getAccessToken());

        You can't do this directly in FacebookTemplate only because the client credentials grant is an OAuth2 concern...not a Facebook concern. Another way of looking at it is that the OAuth templates are primarily for connection-time and the API binding templates are for API time.

        The only reason you must pass the client credentials into TwitterTemplate is because they are required for creating the Authorization header in all requests to the API...per the OAuth 1.0(a) spec. But Facebook, being based on OAuth 2, doesn't require the client's credentials to make API calls, so they are not required when constructing FacebookTemplate.

        One thing that just occurred to me, though: What operations are you wanting to perform with the client token? Not many (or any) of the operations in FacebookTemplate are for client tokens. Of course, you could create a FacebookTemplate and then use the operations in GraphApi or fetch its RestOperations and do whatever you want. But I'd be curious to know what client operations you intend to perform.

        If there's some client operations you would like to be added to FacebookTemplate, let me know via Jira or (better yet) with a pull request. We've been focused on FacebookTemplate's user operations, but I agree that it should be expanded to cover client operations.

        Comment


        • #5
          Originally posted by habuma View Post
          One thing that just occurred to me, though: What operations are you wanting to perform with the client token? Not many (or any) of the operations in FacebookTemplate are for client tokens. Of course, you could create a FacebookTemplate and then use the operations in GraphApi or fetch its RestOperations and do whatever you want. But I'd be curious to know what client operations you intend to perform.

          If there's some client operations you would like to be added to FacebookTemplate, let me know via Jira or (better yet) with a pull request. We've been focused on FacebookTemplate's user operations, but I agree that it should be expanded to cover client operations.
          I want to use FQL queries as this fits best at the moment.
          Basically I want to retrieve a bunch of pages in 1 call and retrieve some fields (e.g. number of "likes").

          Comment


          • #6
            I see. So yeah, I suppose that there are some FQL queries that will work just fine with client credentials.

            If you see an opportunity to extend the API binding with more client-specific operations, let me know. As I said, client-specific operations haven't been in the focus thus far, but I'm starting to see more use for them and want to be sure they're covered.

            Comment


            • #7
              Originally posted by habuma View Post
              ...
              Code:
              OAuth2Template oauth = new OAuth2Template(environment.getProperty("facebook.clientId"),
                                      environment.getProperty("facebook.clientSecret"),
              "https://www.facebook.com/dialog/oauth", "https://graph.facebook.com/oauth/access_token");
              AccessGrant accessGrant = oauth.authenticateClient();
              FacebookTemplate facebook = new FacebookTemplate(accessGrant.getAccessToken());
              Hi Graig.
              I'm trying to get app access token for making subsequent 'app request' call :
              facebook.publish(facebookUserId, "apprequests", data);
              The call is 'App to User request' for user who already had canvas app installed in his fb profile.
              While calling oauth.authenticateClient(); I'm getting error in log (org.apache.http package) like:

              11:41:32.563 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection request: [route: {s}->https://graph.facebook.com][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 100]
              11:41:32.564 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection leased: [id: 1][route: {s}->https://graph.facebook.com][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 100]
              11:41:33.672 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.DefaultClientConnectionOperator - Connecting to graph.facebook.com:443
              11:41:34.087 [http-apr-8080-exec-6] DEBUG o.a.h.c.protocol.RequestAddCookies - CookieSpec selected: best-match
              11:41:34.088 [http-apr-8080-exec-6] DEBUG o.a.h.c.protocol.RequestAuthCache - Auth cache not set in the context
              11:41:34.089 [http-apr-8080-exec-6] DEBUG o.a.h.c.p.RequestProxyAuthentication - Proxy auth state: UNCHALLENGED
              11:41:34.090 [http-apr-8080-exec-6] DEBUG o.a.h.impl.client.DefaultHttpClient - Attempt 1 to execute request
              11:41:34.090 [http-apr-8080-exec-6] DEBUG o.a.h.i.conn.DefaultClientConnection - Sending request: POST /oauth/access_token HTTP/1.1
              11:41:34.091 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "POST /oauth/access_token HTTP/1.1[\r][\n]"
              11:41:34.092 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Accept: application/json, application/*+json[\r][\n]"
              11:41:34.093 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
              11:41:34.093 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Authorization: Basic NTEzODgzNDc4NjMzNTkyOjYzYThhOWM2Z................. .ZWJhOWZh[\r][\n]"
              11:41:34.094 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Content-Length: 29[\r][\n]"
              11:41:34.095 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Host: graph.facebook.com[\r][\n]"
              11:41:34.095 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Connection: Keep-Alive[\r][\n]"
              11:41:34.096 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "User-Agent: Apache-HttpClient/4.2.2 (java 1.5)[\r][\n]"
              11:41:34.097 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "[\r][\n]"
              11:41:34.097 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> POST /oauth/access_token HTTP/1.1
              11:41:34.097 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Accept: application/json, application/*+json
              11:41:34.098 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Content-Type: application/x-www-form-urlencoded
              11:41:34.098 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Authorization: Basic NTEzODgzNDc4NjMzNTkyOjYzYThhOWM2ZWU..............D BhZWJhOWZh
              11:41:34.099 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Content-Length: 29
              11:41:34.099 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Host: graph.facebook.com
              11:41:34.100 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
              11:41:34.100 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.2.2 (java 1.5)
              11:41:34.101 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "grant_type=client_credentials"
              11:41:34.296 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "HTTP/1.1 400 Bad Request[\r][\n]"
              11:41:34.297 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Access-Control-Allow-Origin: *[\r][\n]"
              11:41:34.299 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Cache-Control: no-store[\r][\n]"
              11:41:34.300 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Content-Type: application/json[\r][\n]"
              11:41:34.301 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Expires: Sat, 01 Jan 2000 00:00:00 GMT[\r][\n]"
              11:41:34.302 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Pragma: no-cache[\r][\n]"
              11:41:34.303 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "WWW-Authenticate: OAuth "Facebook Platform" "invalid_client" "Missing client_id parameter."[\r][\n]"
              11:41:34.304 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "X-FB-Rev: 734528[\r][\n]"
              11:41:34.306 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "X-FB-Debug: yWIFgiWJPRfRNAUY3a4fpj2fIxM+D4upa0mE26+eYLo=[\r][\n]"
              11:41:34.307 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Date: Tue, 12 Feb 2013 09:41:36 GMT[\r][\n]"
              11:41:34.308 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Connection: keep-alive[\r][\n]"
              11:41:34.309 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Content-Length: 87[\r][\n]"
              11:41:34.310 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "[\r][\n]"
              11:41:34.311 [http-apr-8080-exec-6] DEBUG o.a.h.i.conn.DefaultClientConnection - Receiving response: HTTP/1.1 400 Bad Request
              11:41:34.312 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << HTTP/1.1 400 Bad Request
              11:41:34.313 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Access-Control-Allow-Origin: *
              11:41:34.314 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Cache-Control: no-store
              11:41:34.315 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Content-Type: application/json
              11:41:34.316 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Expires: Sat, 01 Jan 2000 00:00:00 GMT
              11:41:34.317 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Pragma: no-cache
              11:41:34.320 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << WWW-Authenticate: OAuth "Facebook Platform" "invalid_client" "Missing client_id parameter."
              11:41:34.321 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << X-FB-Rev: 734528
              11:41:34.322 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << X-FB-Debug: yWIFgiWJPRfRN...........upa0mE26+eYLo=
              11:41:34.322 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Date: Tue, 12 Feb 2013 09:41:36 GMT
              11:41:34.323 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Connection: keep-alive
              11:41:34.324 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Content-Length: 87
              11:41:34.326 [http-apr-8080-exec-6] DEBUG o.a.h.impl.client.DefaultHttpClient - Connection can be kept alive indefinitely
              11:41:34.327 [http-apr-8080-exec-6] WARN o.s.web.client.RestTemplate - POST request for "https://graph.facebook.com/oauth/access_token" resulted in 400 (Bad Request); invoking error handler
              11:41:34.330 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "{"error":{"message":"Missing client_id parameter.","type":"OAuthException","code":101}}"
              11:41:34.331 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection [id: 1][route: {s}->https://graph.facebook.com] can be kept alive indefinitely
              11:41:34.332 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection released: [id: 1][route: {s}->https://graph.facebook.com][total kept alive: 1; route allocated: 1 of 5; total allocated: 1 of 100]
              11:41:38.560 [http-apr-8080-exec-6] ERROR c.i.w.c.e.EventRegisterController - Publishing REST error
              org.springframework.web.client.HttpClientErrorExce ption: 400 Bad Request
              at org.springframework.web.client.DefaultResponseErro rHandler.handleError(DefaultResponseErrorHandler.j ava:88) ~[spring-web-3.2.0.RELEASE.jar:3.2.0.RELEASE]
              There is something I don't quite understand...

              I debugged initalization public OAuth2Template(........)
              Code:
              	public OAuth2Template(String clientId, String clientSecret, String authorizeUrl, String authenticateUrl, String accessTokenUrl) {
              		Assert.notNull(clientId, "The clientId property cannot be null");
              		Assert.notNull(clientSecret, "The clientSecret property cannot be null");
              		Assert.notNull(authorizeUrl, "The authorizeUrl property cannot be null");
              		Assert.notNull(accessTokenUrl, "The accessTokenUrl property cannot be null");
              		this.clientId = clientId;
              		this.clientSecret = clientSecret;
              		String clientInfo = "?client_id=" + formEncode(clientId);
              		this.authorizeUrl = authorizeUrl + clientInfo;
              		if (authenticateUrl != null) {
              			this.authenticateUrl = authenticateUrl + clientInfo;
              		} else {
              			this.authenticateUrl = null;
              		}
              		this.accessTokenUrl = accessTokenUrl;
              		this.restTemplate = createRestTemplate();
              		if (!useParametersForClientAuthentication) {
              			restTemplate.getInterceptors().add(new PreemptiveBasicAuthClientHttpRequestInterceptor(clientId, clientSecret));
              		}
              	}
              The RED line is executed and I'm not sure if I initialize it correctly for my case.
              Last edited by blandger; Feb 12th, 2013, 05:14 AM. Reason: added more clarification info

              Comment


              • #8
                I don't think that the authenticateUrl matters here. It's fine that it's null. That URL is only used in some cases where a provider offers a special URL for authorization that's specifically for sign-in-with-provider functionality. For example, Twitter offers a special URL for authentication that differs from authorization in that it won't force the user to explicitly authorize if a previous authorization was already given. Even if you don't provide that, the OAuth2Template will fall back and use the authorization URL instead.

                But for client authentication, which is what you're doing here, neither the authentication nor authorization URLs are used. it's the access token URL that's in play.

                From the log messages it's saying that the client ID wasn't provided. Can you confirm that there *is* a client ID being passed into the constructor? It may not be null (there are assertions to guarantee that), but if it's empty then that's just as big of a problem. (Maybe I should make those assertions stronger to enforce non-blank and non-null values.)

                Comment


                • #9
                  Yes, I can confirm, clientId is definitely gets correct value and initialized in constructor:

                  In constructor's code :
                  Code:
                  this.clientSecret = clientSecret;
                  String clientInfo = "?client_id=" + formEncode(clientId);
                  this.authorizeUrl = authorizeUrl + clientInfo; // value here = https://www.facebook.com/dialog/oauth?client_id=5138XXX786XXX92
                  if (authenticateUrl != null) {
                      this.authenticateUrl = authenticateUrl + clientInfo;
                  } else {
                      this.authenticateUrl = null;
                  }
                  but on the line:
                  if (authenticateUrl != null) {...
                  it goes to ELSE statement and makes: this.authenticateUrl = null;

                  That's why I'm asking about it...

                  Comment


                  • #10
                    Again, it's totally fine that the authenticateUrl is null. It is almost always null for most providers. During the authorization code flow in ProviderSignInController, it will use it if it's not null, but will use the authorizationUrl if the authenticationUrl is null. I do not believe that this has anything to do with your problem because that URL is not used for client authorization.

                    Here's your problem, though: The client_id parameter is not being sent in access token request. The quick fix is to do this because you call authenticateClient():

                    Code:
                    oauth.setUseParametersForClientAuthentication(true);
                    That should make things work. For the lengthy explanation of why, read on...

                    Per the latest (and now final) drafts of the OAuth2 specification, client credentials *should* be sent in an HTTP Basic authentication header and *not* in query parameters. Older drafts of the specification said that they could be sent in query parameters. Facebook still wants them in query parameters.

                    By default, OAuth2Template will do what the latest/final draft specifies and sends them in an HTTP Basic header. But that doesn't work for Facebook (or most providers, actually, because most providers haven't updated their implementation to the latest spec). But if you set useParametersForClientAuthentication to true, then the client credentials will be sent in query parameters and not in an HTTP Basic header; thus making Facebook happy.

                    Comment


                    • #11
                      Now it works much better but still is not quite good. Weird error at the end of successful call.

                      Log looks :
                      23:03:42.955 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection request: [route: {s}->https://graph.facebook.com][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 100]
                      23:03:43.037 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection leased: [id: 0][route: {s}->https://graph.facebook.com][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 100]
                      23:03:43.315 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.DefaultClientConnectionOperator - Connecting to graph.facebook.com:443
                      23:03:43.958 [http-apr-8080-exec-6] DEBUG o.a.h.c.protocol.RequestAddCookies - CookieSpec selected: best-match
                      23:03:44.122 [Finalizer] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection manager is shutting down
                      23:03:44.124 [Finalizer] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection manager shut down
                      23:03:44.162 [http-apr-8080-exec-6] DEBUG o.a.h.c.protocol.RequestAuthCache - Auth cache not set in the context
                      23:03:44.164 [http-apr-8080-exec-6] DEBUG o.a.h.c.p.RequestProxyAuthentication - Proxy auth state: UNCHALLENGED
                      23:03:44.167 [http-apr-8080-exec-6] DEBUG o.a.h.impl.client.DefaultHttpClient - Attempt 1 to execute request
                      23:03:44.168 [http-apr-8080-exec-6] DEBUG o.a.h.i.conn.DefaultClientConnection - Sending request: POST /oauth/access_token HTTP/1.1
                      23:03:44.170 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "POST /oauth/access_token HTTP/1.1[\r][\n]"
                      23:03:44.176 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Accept: application/json, application/*+json[\r][\n]"
                      23:03:44.177 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
                      23:03:44.178 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Authorization: Basic NTEzODgzNDc4NjMzNTkyOjYzYThhOWM2ZWU5MjXXXXXXXXXXXX XXXXhZWJhOWZh[\r][\n]"
                      23:03:44.178 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Content-Length: 102[\r][\n]"
                      23:03:44.179 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Host: graph.facebook.com[\r][\n]"
                      23:03:44.179 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "Connection: Keep-Alive[\r][\n]"
                      23:03:44.180 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "User-Agent: Apache-HttpClient/4.2.2 (java 1.5)[\r][\n]"
                      23:03:44.180 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "[\r][\n]"
                      23:03:44.181 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> POST /oauth/access_token HTTP/1.1
                      23:03:44.181 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Accept: application/json, application/*+json
                      23:03:44.181 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Content-Type: application/x-www-form-urlencoded
                      23:03:44.182 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Authorization: Basic NTEzODgzNDc4NjMzNTkyOjYzYThhOWM2ZWUXXXXXXXXXXXXXXX XXXXXXhOWZh
                      23:03:44.182 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Content-Length: 102
                      23:03:44.183 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Host: graph.facebook.com
                      23:03:44.183 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
                      23:03:44.183 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.2.2 (java 1.5)
                      23:03:44.184 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - >> "client_id=513883478XXXXXX&client_secret=63a8a9cXX XXXXXXXXXXba9fa&grant_type=client_credentials"
                      23:03:44.371 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "HTTP/1.1 200 OK[\r][\n]"
                      23:03:44.381 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Access-Control-Allow-Origin: *[\r][\n]"
                      23:03:44.382 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Cache-Control: private, no-cache, no-store, must-revalidate[\r][\n]"
                      23:03:44.382 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Content-Type: text/plain; charset=UTF-8[\r][\n]"
                      23:03:44.383 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Expires: Sat, 01 Jan 2000 00:00:00 GMT[\r][\n]"
                      23:03:44.384 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Pragma: no-cache[\r][\n]"
                      23:03:44.384 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "X-FB-Rev: 734528[\r][\n]"
                      23:03:44.385 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "X-FB-Debug: OG/tgqsKDXegiszj+PinqR8Xzsmo8P+j1KXEUv/fmFo=[\r][\n]"
                      23:03:44.385 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Date: Tue, 12 Feb 2013 21:03:46 GMT[\r][\n]"
                      23:03:44.386 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Connection: keep-alive[\r][\n]"
                      23:03:44.387 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "Content-Length: 56[\r][\n]"
                      23:03:44.387 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "[\r][\n]"
                      23:03:44.391 [http-apr-8080-exec-6] DEBUG o.a.h.i.conn.DefaultClientConnection - Receiving response: HTTP/1.1 200 OK
                      23:03:44.392 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << HTTP/1.1 200 OK
                      23:03:44.392 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Access-Control-Allow-Origin: *
                      23:03:44.393 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Cache-Control: private, no-cache, no-store, must-revalidate
                      23:03:44.393 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Content-Type: text/plain; charset=UTF-8
                      23:03:44.394 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Expires: Sat, 01 Jan 2000 00:00:00 GMT
                      23:03:44.394 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Pragma: no-cache
                      23:03:44.395 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << X-FB-Rev: 734528
                      23:03:44.395 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << X-FB-Debug: OG/tgqsKDXegiszj+PinqR8Xzsmo8P+j1KXEUv/fmFo=
                      23:03:44.396 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Date: Tue, 12 Feb 2013 21:03:46 GMT
                      23:03:44.396 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Connection: keep-alive
                      23:03:44.396 [http-apr-8080-exec-6] DEBUG org.apache.http.headers - << Content-Length: 56
                      23:03:44.428 [http-apr-8080-exec-6] DEBUG o.a.h.impl.client.DefaultHttpClient - Connection can be kept alive indefinitely
                      23:03:44.504 [http-apr-8080-exec-6] DEBUG org.apache.http.wire - << "access_token=5138XXXXXXX3592|G9CdXXXXXXXXXXXXkYn8 j70"
                      23:03:44.505 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection [id: 0][route: {s}->https://graph.facebook.com] can be kept alive indefinitely
                      23:03:44.506 [http-apr-8080-exec-6] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection released: [id: 0][route: {s}->https://graph.facebook.com][total kept alive: 1; route allocated: 1 of 5; total allocated: 1 of 100]
                      23:05:04.805 [http-apr-8080-exec-6] ERROR c.i.w.c.e.EventRegisterController - Publishing REST error
                      org.springframework.web.client.RestClientException : Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map] and content type [text/plain;charset=UTF-8]

                      at org.springframework.web.client.HttpMessageConverte rExtractor.extractData(HttpMessageConverterExtract or.java:107) ~[spring-web-3.2.0.RELEASE.jar:3.2.0.RELEASE]
                      at org.springframework.web.client.RestTemplate.doExec ute(RestTemplate.java:492) ~[spring-web-3.2.0.RELEASE.jar:3.2.0.RELEASE]
                      at org.springframework.web.client.RestTemplate.execut e(RestTemplate.java:447) ~[spring-web-3.2.0.RELEASE.jar:3.2.0.RELEASE]
                      at org.springframework.web.client.RestTemplate.postFo rObject(RestTemplate.java:295) ~[spring-web-3.2.0.RELEASE.jar:3.2.0.RELEASE]
                      at org.springframework.social.oauth2.OAuth2Template.p ostForAccessGrant(OAuth2Template.java:221) ~[spring-social-core-1.1.0.BUILD-SNAPSHOT.jar:1.1.0.BUILD-SNAPSHOT]
                      at org.springframework.social.oauth2.OAuth2Template.a uthenticateClient(OAuth2Template.java:187) ~[spring-social-core-1.1.0.BUILD-SNAPSHOT.jar:1.1.0.BUILD-SNAPSHOT]
                      at org.springframework.social.oauth2.OAuth2Template.a uthenticateClient(OAuth2Template.java:174) ~[spring-social-core-1.1.0.BUILD-SNAPSHOT.jar:1.1.0.BUILD-SNAPSHOT]
                      .................
                      That happens on call:
                      accessGrant = oauth.authenticateClient();

                      Comment


                      • #12
                        I can debug Response from FB in IDE and see it contains some data.
                        See attach with screenshot.

                        UPDATE:
                        Odd screen after upload.
                        There is LinkedValuedMap with 3 Map entries: client_id + value, client_secret + value, grant_type = client_credentials.
                        I don't know if that important for error description, but I decided to give that info.

                        Code for error looks like:
                        Code:
                        package org.springframework.web.client;
                        
                        public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> {
                        ...........
                        	public T extractData(ClientHttpResponse response) throws IOException {
                        .......
                        		for (HttpMessageConverter messageConverter : this.messageConverters) {
                        .....
                        		}
                        		throw new RestClientException(
                        				"Could not extract response: no suitable HttpMessageConverter found for response type [" +
                        						this.responseType + "] and content type [" + contentType + "]");
                        	}
                        Last edited by blandger; Feb 12th, 2013, 04:28 PM.

                        Comment


                        • #13
                          Craig, don't you have any more ideas why it can't find suitable 'HttpMessageConverter messageConverter' for received answer from FB ?
                          May I can do deeper debug and see structure/answer/response it can't parse properly?

                          Comment


                          • #14
                            Sorry about that. I've been struggling to get the 1.1.0.M2 releases out and only occasionally glancing at the forums. I saw your post, but thought it might take longer to resolve than I had time for, so I thought I'd just come back to it eventually.

                            In short, Facebook's an odd one and not consistent with other OAuth2 providers. That's why Spring Social Facebook has its own subclass of OAuth2Template specifically for Facebook: FacebookOAuth2Template. You can see the full code for FacebookOAuth2Template at https://github.com/SpringSource/spri...2Template.java.

                            You'll see there that a special message converter is set to handle Facebook's non-standard way of returning authorization details. If you're working with Facebook, you're probably better using that implementation directly. But if you want to use OAuth2Template, then you'll need to do something similar to what you see in FacebookOAuth2Template.

                            Comment


                            • #15
                              Thanks a lot, I've changed
                              OAuth2Template oauth = new OAuth2Template(...)
                              to
                              OAuth2Template oauth = new FacebookOAuth2Template(...)

                              now it works as expected and publishes app request to FB user's profile.

                              Comment

                              Working...
                              X