Announcement Announcement Module
No announcement yet.
Spring Social and Plurk Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Social and Plurk

    I'm trying to implement a Plurk provider for Spring Social so users can signin with their Plurk account in my webapp. API detailed here: it is based in Oauth 1.0a

    I'm using the existing Twitter implementation as a guide. I'm encountering some trouble though.

    I'm not sure how much of the oauth handshake is a success, but I am redirected to the Plurk page where I'm asked to authorise the app, but when I get to the point where the user profile is obtained I am being sent back the following response:

    {"error_text": "40002:unknown oauth request"}

    I added a custom ClientHttpRequestInterceptor so I could examime the request:

    Method: GET
    Headers: {Accept=[application/json], Content-Length=[0]}

    Should there be an Authorization header here? I gather this indicates authorization was not successful?

    Apologies if this post is a bit vague - I'm not familiar with oauth but I'm hoping someone with more experience can provide more insight and maybe point to where/how I should to determine where this might be going wrong.

  • #2
    Can you post code showing your PlurkConnectionFactory. Also, if you're testing usage of PlurkConnectionFactory directly when this error occurs, can you post that code. Finally are using it in a Spring MVC web app like spring-social-showcase - if so, can you show how you are configuring it there.

    Alternatively, make this a lot simpler by creating a github repository for your Spring Social Plurk work and we can just review the code and tests there



    • #3
      Hi Keith,

      I uploaded the current code to github:

      So far I have been testing it in the webapp, but I will work on some test cases.

      Configured as below:

      @Scope(value="singleton", proxyMode=ScopedProxyMode.INTERFACES) 
      public ConnectionFactoryLocator connectionFactoryLocator()
      	ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
      	registry.addConnectionFactory(new TwitterConnectionFactory(environment.getProperty("twitter.consumerKey"), environment.getProperty("twitter.consumerSecret")));
      	registry.addConnectionFactory(new FacebookConnectionFactory(environment.getProperty("facebook.clientId"), environment.getProperty("facebook.clientSecret")));
      	registry.addConnectionFactory(new PlurkConnectionFactory(environment.getProperty("plurk.consumerKey"), environment.getProperty("plurk.consumerSecret")));	
      	return registry;
      @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)	
      public Plurk plurk()
      	Connection<Plurk> plurk = connectionRepository().findPrimaryConnection(Plurk.class);
      	return plurk != null ? plurk.getApi() : new PlurkTemplate();
      @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
      public Plurk plurkApi(ConnectionRepository connectionRepository) {
      	Connection<Plurk> connection = connectionRepository.findPrimaryConnection(Plurk.class);
      	return connection != null ? connection.getApi() : null;


      • #4
        Thanks for pushing this to github, makes things so much easier.

        This line in your PlurkTemplate(String, String, String, String) constructor is likely the problem:
        getRestTemplate().setInterceptors( new ClientHttpRequestInterceptor[] { new HttpInterceptor() } );
        If you review what happens in the super AbstractOAuth1ApiBinding(String, String, String, String) constructor you're calling, you'll see a call to ProtectedResourceClientFactory.create(credentials) that produces the RestTemplate instance wired with a OAuth1RequestInterceptor. This interceptor is the object that signs each request with the Authorization header before it is executed. Your call above is overwriting the set of interceptors, so the required OAuth signing behavior is being removed.

        Getting rid of your manual getRestTemplate().setInterceptors(...) call should resolve the problem. That said, I can see how you might want to plug in your own interceptors beyond what is already configured. Unfortunately, RestTemplate's strict JavaBeans-style configuration API doesn't make it easy to add an another interceptor to the set of pre-existing interceptors. I recommend you open a JIRA at requesting an improvement here--the addition of an addInterceptor(...) method would be welcome before 3.1.0.RC1.

        Last edited by Keith Donald; Aug 27th, 2011, 02:56 PM.


        • #5
          Thanks for taking the time to examine the code - much appreciated!

          Ironically I only implemented the interceptor so I could peek into the request/response because of a previous issue. I used TCPMon instead.

          The previous issue being that there was no suitable HttpMessageConverter for the html content being returned from the Plurk server.

          From what I can see in TCPMon the response is a 301 Moved Permanently.

          I changed the initial request line in TCPMon to:

          GET HTTP/1.1

          Using the using absolute URL seems to resolve this issue, but I'm not yet sure how I can change this in the code.


          • #6
            Aside from the fact that configuring the interceptors could be easier than it is, I'm still unclear as to what you were doing when you got the 301 response. I'm looking at your code and the Plurk API and see nothing that would've caused the 301 or have resulted in HTML being returned. In fact, I quickly threw together some test code and was able to fetch my Plurk profile with no problem. But then again, I may be looking for the problem in the wrong place.
            Last edited by habuma; Aug 30th, 2011, 03:33 PM.


            • #7
              I think the problem was TCPMon - it was changing the initial request line to use abs_path instead of absoluteURI which I think was causing the 301. But as I was still getting a "html" response even if I was removing the interference of TCPMon.

              Eventually what I did was create a custom HttpMessageConverter to read text/html so I could see exactly what was in the response header/body.

              The problem was that the content-type in the response header was text/html (even though the content was json). I contacted the Plurk dev team to notify them and they sent me back an email this morning to say it had been fixed. I just tested it now and it's working correctly.


              • #8
                That's great that they fixed it. Also explains why it worked for me today. Glad to hear that it's working now!