hwangjungseok / oauth-signpost

Automatically exported from code.google.com/p/oauth-signpost
0 stars 0 forks source link

"Invalid Signature" when POSTing to twitter. #15

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
When posting to twitter using code similar to the following:

----------------------------
final URL url = new URL("http://twitter.com/statuses/update.xml");
final HttpURLConnection request = url.openConnection();

request.setRequestMethod("POST");
request.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
request.setRequestProperty("Content-Length", "" +
Integer.toString(params.getBytes().length));
request.setRequestProperty("Content-Language", "en-US");
request.setUseCaches(false);
request.setDoInput(true);
request.setDoOutput(true);
consumer.sign(request);
try {
   final DataOutputStream out = new
DataOutputStream(request.getOutputStream());
   out.writeBytes("status=test");
   out.flush();
   out.close();
} catch (IOException ex) { ex.printStackTrace(); }
----------------------------
(The actual code can be found here:
http://git.dmdirc.com/cgit.cgi/client-shane/tree/src/com/dmdirc/addons/parser_tw
itter/api/TwitterAPI.java?h=twitter
- setStatus(), postXML(), getXML() and signURL())

This gives the output:
----------------------------
<?xml version="1.0" encoding="UTF-8"?>
<hash>
 <request>/statuses/update.xml</request>
 <error>Incorrect signature</error>
</hash>
----------------------------

Everything works fine when using GET.

Original issue reported on code.google.com by Shane...@gmail.com on 5 Aug 2009 at 12:51

GoogleCodeExporter commented 8 years ago
Some searching has found:
http://groups.google.com/group/twitter-development-talk/msg/6ea8dd6fbee88e9f
which I think may be related, as the given code worked fine a few days prior.

Original comment by Shane...@gmail.com on 5 Aug 2009 at 12:55

GoogleCodeExporter commented 8 years ago
I'm having the same problem, unable to sign POST requests only GET.

"consumer.sign(request)" works fine on GET not on POST..are we missing any 
request
parameters??

Original comment by tulio.do...@gmail.com on 6 Aug 2009 at 11:01

GoogleCodeExporter commented 8 years ago
The following work around works fine. put the payload into the URL rather than
separately, and set content-length to 0 so that proxies like Squid won't break 
(Squid
requires a content-length on PUT or POST even if there is no content):

----------------------------
final String params = "status=test";
final URL url = new URL("http://twitter.com/statuses/update.xml?" + params);
final HttpURLConnection request = url.openConnection();

request.setRequestMethod("POST");
request.setRequestProperty("Content-Length", "0");
request.setUseCaches(false);
consumer.sign(request);
----------------------------

This suggests that the POST payload isn't being signed correctly.

Original comment by Shane...@gmail.com on 6 Aug 2009 at 11:20

GoogleCodeExporter commented 8 years ago
Wow you are the saviour!!
Thanks a lot Shane that works like a charm! I spent the whole day yesterday and
couldn't find a way round it..
Cheers
Tulio

Original comment by tulio.do...@gmail.com on 6 Aug 2009 at 11:40

GoogleCodeExporter commented 8 years ago
Because request.getOutputStream() opens the connection I don't think it will be
possible to correctly sign using that method (which I presume is mostly used 
for file
uploads, which aren't covered by oauth.

I'd love to know if there was a better way of doing this than specifying the 
params
in the URL however.

Original comment by Shane...@gmail.com on 6 Aug 2009 at 11:52

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Thats true, if oauth doesn't support file uploads anyway, users should be 
alright
appending the post data to the URL..If I come across a better way of doing this 
will
definitely let you know
Cheer

Original comment by tulio.do...@gmail.com on 6 Aug 2009 at 12:18

GoogleCodeExporter commented 8 years ago
Hey guys,

this is not a problem with Twitter, and it's also not actually a bug in 
Signpost.
This problem is a consequence of how HttpURLConnection POSTs work. I already
commented on this issue here: http://groups.google.com/group/signpost-
users/msg/8c9c0b47de68d032

In a nutshell, the problem lies within how data is sent using a URLConnection 
type
request. URLConnection is based around streams. That means, as soon as you add a
payload to your message, you immediately send that data over the wire to the 
service
endpoint. There is no way for Signpost to consider that data for request 
signing,
because it's not buffered and already gone (or not yet there) when signing the 
message.

Hence, since POST params do not pass through message signing, authorization 
fails.

I'll leave this ticket open, but currently I don't see any good solution to 
this.

Just curious: Why do you use URLConnection anyway? Apache HttpComponents or 
JettyHttp would make your life so much easier, and this problem would be non 
existent.

Original comment by m.kaepp...@gmail.com on 6 Aug 2009 at 12:19

GoogleCodeExporter commented 8 years ago
Thanks for the post, will use Apache HttpComponents instead..

Original comment by tulio.do...@gmail.com on 6 Aug 2009 at 12:38

GoogleCodeExporter commented 8 years ago
I use (HTTP)URLConnection for a few reasons:

The example code for twitter on the wiki used it and I wrote the code based 
around
that so when it came time to POST stuff, i just adapted the code.

Also, I prefer to stick to the built in jdk classes where possible unless there 
is a
compelling reason not to - I don't like needing lots of external dependancies.

(One of the reasons I'm writing my own twitter library rather than using 
another one
is that the one I used in the past didn't support oauth (this is the main 
reason) but
also had about 15 external dependencies that weren't mentioned anywhere)

I appreciate the reason for this not working, I hadn't fully investigated the 
cause
of the problem when I submitted the bug report, and had assumed that because it 
had
worked before twitter fixed their validation that it was possible for signpost 
to see
the submitted data. (I did then try signing after writing out the data which 
gave an
exception that made me realise this was not actually the case)

I'm happy wnough with the work around of putting the parameters into the URL, 
but I
presume theres a better way without needing an external library.

Original comment by Shane...@gmail.com on 6 Aug 2009 at 12:39

GoogleCodeExporter commented 8 years ago

Original comment by m.kaepp...@gmail.com on 11 Sep 2009 at 9:07

GoogleCodeExporter commented 8 years ago
Issue 17 has been merged into this issue.

Original comment by m.kaepp...@gmail.com on 8 Oct 2009 at 7:53

GoogleCodeExporter commented 8 years ago
using Apache HttpComponents and it fails with 401 (invalid signature)-

HttpPut request = new 
HttpPut("http://api.myspace.com/v1/users/475585660/status")         

request.addHeader("Content-Type", "application/x-www-form-urlencoded");
BasicHttpEntity entity = new BasicHttpEntity();
entity.setContent(new StringBufferInputStream("status=hi"));

request.setEntity(entity);
consumer.sign(request);

            // send the request         
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);

Original comment by kbsan...@gmail.com on 29 Oct 2009 at 10:29

GoogleCodeExporter commented 8 years ago
I don't think your problem is related. This issue report is about POSTing data 
using
HttpURLConnection, which is known to be a problem.

Please turn to the Google Group first and post all details and how your problem 
can
be reproduced, or if you're /sure/ it's a bug, open a new ticket.

Original comment by m.kaepp...@gmail.com on 29 Oct 2009 at 10:53

GoogleCodeExporter commented 8 years ago
Faced same problem with Apache HttpClient. Interesting bit is thatis POSTs ok 
when
httpclient 4.0 but fails with "Invalid Signature" - I changed onli lib used, 
not code. 

Hope it helps someone. The only solution I currently found is to rollback to 
4.0.

Original comment by warlordk...@gmail.com on 20 Jan 2010 at 1:15

GoogleCodeExporter commented 8 years ago
Found the source of the problem with Apache HttpClient 4.x (any version could be
affected)

oauth.signpost.signature.SignatureBaseString

    private void collectBodyParameters(Collection<Parameter> parameters)
            throws IOException {

        // collect x-www-form-urlencoded body params
        String contentType = request.getContentType();
        if (contentType != null && contentType.equals(OAuth.FORM_ENCODED)) {   <--- ISSUE
            InputStream payload = request.getMessagePayload();
            parameters.addAll(OAuth.decodeForm(payload));
        }
    }

issue: contentType.equals(OAuth.FORM_ENCODED)
we could see that content type is checked to be equal to
"application/x-www-form-urlencoded", but in real life contentType of POST could 
be
e.g. "application/x-www-form-urlencoded; charset=ISO-8859-1". See RFC-2616
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

So in this case .equals fails and signpost omits POST params from signature 
calculation.

Original comment by warlordk...@gmail.com on 20 Jan 2010 at 2:04

GoogleCodeExporter commented 8 years ago
Yes I'm aware of that problem, will be fixed with the next release (i.e. very 
soon).

Original comment by m.kaepp...@gmail.com on 20 Jan 2010 at 2:12

GoogleCodeExporter commented 8 years ago
I just released 1.2, which fixes this problem.

Original comment by m.kaepp...@gmail.com on 27 Jan 2010 at 10:51

GoogleCodeExporter commented 8 years ago
I'm not gonna fix the problem originally reported. There's enough ways to work 
around 
this (e.g. passing parameters in the query strings or switching to a decent 
HTTP 
library like Apache HttpClient) and fixing this in the lib would require 
hacking 
around the HttpURLConnection implementation.

Sorry folks.

Original comment by m.kaepp...@gmail.com on 21 Mar 2010 at 1:35

GoogleCodeExporter commented 8 years ago
No probs mate, as long as we can get it to work..whether its putting the 
payload in
the URL or using Apache HttpClient then its fine. 

Tulio

Original comment by tulio.do...@gmail.com on 21 Mar 2010 at 1:46

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Issue 35 has been merged into this issue.

Original comment by m.kaepp...@gmail.com on 23 Mar 2010 at 9:02