Announcement Announcement Module
Collapse
No announcement yet.
OAuth 1.0 and extra request parameters Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • OAuth 1.0 and extra request parameters

    Hi All,
    Got problems while signing post request with extra parameters. As I read, request parameters, using method POST should be specified in request body and request should have header - "Content-Type: application/x-www-form-urlencoded".
    I use next code for that:
    Code:
    MultiValueMap postParams = new LinkedMultiValueMap();
    postParams.add("status", "Update my status on Twitter");
    authRestTemplate.postForLocation("http://api.twitter.com/1/statuses/update.xml", postParams);
    To write postParams to request body template uses standard FormHttpMessageConverter. But, problem is, that messageConverter writes parameters to body AFTER OAuthClientHttpRequestFactory signed request, thus parameter status="Update my status on Twitter" is not used on making signature:
    Code:
    String queryString = this.support.getOAuthQueryString(this.resource, accessToken, uri.toURL(), httpMethod.name(), this.additionalOAuthParameters);
    So, this problem exists only for POST methods, because for GET methods in CoreOAuthConsumerSupport.loadOAuthParameters(...)
    Code:
    String query = requestURL.getQuery();
        if (query != null) {
    //here, all params from query are handled correctly
    }
    all parameter in query are parsed and used to calculate signatures.
    Any ideas, how to fix it?

  • #2
    That would probably be a bug. Can you open a JIRA issue describing the problem and expected behavior?

    Comment


    • #3
      Not sure. I think RestTemplate + oauth HttpFactory decoration is not suitable for it at all. I thought about it and ended up by writing own MessageConverter for that.
      Does anybody from this project tell me his thoughts about it?
      Here is my code (mainly copy-pasted from OAuthClientHttpRequestFactory):
      Code:
      public class OAuthPostMessageConverter extends FormHttpMessageConverter {
      
          private ProtectedResourceDetails resource;
          private OAuthConsumerSupport support =  new CoreOAuthConsumerSupport();;
          
          @Override
          public void write(MultiValueMap<String, ? > map, MediaType contentType,
              HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
              OAuthSecurityContext context = OAuthSecurityContextHolder.getContext();
              ClientHttpRequest req = (ClientHttpRequest) outputMessage;
              if (context == null) {
                throw new IllegalStateException("No OAuth security context has been established. Unable to access resource '" + this.resource.getId() + "'.");
              }
      
              Map<String, OAuthConsumerToken> accessTokens = context.getAccessTokens();
              OAuthConsumerToken accessToken = accessTokens == null ? null : accessTokens.get(this.resource.getId());
              if (accessToken == null) {
                throw new AccessTokenRequiredException("No OAuth security context has been established. Unable to access resource '" + this.resource.getId() + "'.", resource);
              }
              Map<String, String> params = new HashMap<String, String>();
              for (Map.Entry<String, ?> entry : map.entrySet()) {
                  @SuppressWarnings("unchecked")
                  List<String> value= (List<String>) entry.getValue();
                  params.put(entry.getKey(), value.get(0));
              }
              String authHeader = this.support.getAuthorizationHeader(this.resource, accessToken, req.getURI().toURL(), req.getMethod().name(), params);
              req.getHeaders().add("Authorization", authHeader);
      
              super.write(map, contentType, outputMessage);
          }
      
          
          public void setResource(ProtectedResourceDetails resource) {
              this.resource = resource;
          }
      
          
          public void setSupport(OAuthConsumerSupport support) {
              this.support = support;
          }
      
      }
      Last edited by Hunger; Feb 22nd, 2011, 09:46 AM.

      Comment


      • #4
        I think you've got the right idea. I think the RestTemplate is used primarily for convenience, but it looks like in your case you have to do this with custom code. But it sounds like something like this could be provided as an additional utility.

        Comment


        • #5
          Again, not sure. I think oauth rest template's logic is wrong. It signs request BEFORE code manipulation, but it should do it AFTER all manipulations with request, because content of request could be changed in any place, thus auth signature become wrong.

          Comment

          Working...
          X