Thanks Taylor and Mike.. my hours of heartache are solved :)
On May 21, 3:03 am, Taylor Singletary <taylorsinglet...@twitter.com> wrote: > Mike Dice gets the dice :) Glad you figured it out. > > The best way to think of this is that a POST body being sent to Twitter is > by definition URL Escaped when valid. The OAuth spec asks you to URL escape > parameter keys and values when building the signature base string, which > means that you take each key and value from the URL-escaped POST body and > escape them again. > > Cheers! > T > > > > On Thu, May 20, 2010 at 9:45 AM, Mike Dice <mikedice...@gmail.com> wrote: > > Oh wait... > > Here is the crucial piece I missed, which you said below: > > > Which when passed into your Signature Base String will get URL escaped > > > again: > > > I have to escape my message, then escape the escaped message for use in the > > signing base string. The %25 is the escaped '%'. My app is working now :-) > > > On Thu, May 20, 2010 at 9:25 AM, MikeDice417 <mikedice...@gmail.com>wrote: > > >> Taylor, I am having a very similar problem. I think I am missing some > >> crucial point about the encoding method that needs to be used with > >> twitter. THe library I am working on has successfully authenticated > >> using Oauth with twitter. I have my access_token and > >> access_token_secret and I want to update my twitter status. If I only > >> send one word as my status, the update works. If I send two words > >> separated by a space the update does not work. I get back a 401 > >> unauthorized response to the udpate request. My signing base string > >> POST request and response are below. As noted I have already > >> negotiated and OAuth access token so I don't show that information. > > >> I noticed one thing in your example that is different from my code. In > >> my signing base string a space is encoded as %20. In yours, a space is > >> encoded as %2520. Do you have any ideas what the difference is between > >> your encoding method and mine? > > >> Here is my signature base string: > >> POST&http%3A%2F%2Fapi.twitter.com <http://2fapi.twitter.com/> > >> %2F1%2Fstatuses > >> %2Fupdate.xml&oauth_consumer_key%3Dbt7VUyYJ4adSHxIrGJYFxQ%26oauth_nonce > >> %3DISJERMBJCAQEYGUAWXAKQXTFPGFATRFUOQORGAMD%26oauth_signature_method > >> %3DHMAC-SHA1%26oauth_timestamp%3D1274372472%26oauth_token > >> %3D136131415-1kvYKiXUP8kS7yq39cGqmruDzvsF7uOoLPSK7Eh1%26oauth_version > >> %3D1.0%26status%3Dtest%20this > > >> And the POST request I made follows below: > > >> POSThttp://api.twitter.com/1/statuses/update.xmlHTTP/1.1 > >> Authorization: OAuth oauth_consumer_key="bt7VUyYJ4adSHxIrGJYFxQ", > >> oauth_nonce="ISJERMBJCAQEYGUAWXAKQXTFPGFATRFUOQORGAMD", > >> oauth_signature_method="HMAC-SHA1", oauth_timestamp="1274372472", > >> oauth_token="136131415-1kvYKiXUP8kS7yq39cGqmruDzvsF7uOoLPSK7Eh1", > >> oauth_version="1.0", oauth_signature="mkF7LWE4UqscMsjUlLQTRJFDFhg%3D" > >> Content-Type: application/x-www-form-urlencoded > >> Host: api.twitter.com > >> Content-Length: 18 > >> Expect: 100-continue > > >> status=test%20this > > >> And the POST response > >> HTTP/1.1 401 Unauthorized > >> Connection: Keep-Alive > >> Connection: Proxy-Support > >> Content-Length: 135 > >> Via: 1.1 RED-PRXY-21 > >> Expires: Thu, 20 May 2010 16:51:16 GMT > >> Date: Thu, 20 May 2010 16:21:16 GMT > >> Content-Type: application/xml; charset=utf-8 > >> Server: hi > >> Proxy-Support: Session-Based-Authentication > >> Status: 401 Unauthorized > >> WWW-Authenticate: Basic realm="Twitter API" > >> Cache-Control: no-cache, max-age=1800 > >> Set-Cookie: k=131.107.0.71.1274372476598501; path=/; expires=Thu, 27- > >> May-10 16:21:16 GMT; domain=.twitter.com > >> Set-Cookie: guest_id=127437247670844927; path=/; expires=Sat, 19 Jun > >> 2010 16:21:16 GMT > >> Set-Cookie: > > >> _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCDLPhLYoAToHaWQiJTE1M2MzMzg5ODc4MzI4% > >> 250ANDlkMWMwYjFlMzZkMTlkYTdkIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy > >> %250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA-- > >> c409bb092a71a15b4823075255ee464267520fba; domain=.twitter.com; path=/ > >> Vary: Accept-Encoding > > >> <?xml version="1.0" encoding="UTF-8"?> > >> <hash> > >> <request>/1/statuses/update.xml</request> > >> <error>Incorrect signature</error> > >> </hash> > > >> On May 20, 6:45 am, Taylor Singletary <taylorsinglet...@twitter.com> > >> wrote: > >> > Hi Onn, > > >> > It's best to consider all space characters as %20 when building both > >> your > >> > POST body and signature base string -- instead of using " " or "+", just > >> get > >> > right down to it as "%20". > > >> > I'll show you how a pretty varied string of characters would be > >> correctly > >> > encoded both for the POST body and signature base string: > > >> > Given that you want to set a status that says: "I can tweet many kinds > >> of > >> > characters ! (* $ @ 漢字 عربي)" > > >> > Your POST body should have that string encoded as: > > >> status=I%20can%20tweet%20many%20kinds%20of%20characters%20%21%20%28%2A%20%2 > >> 4%20%40%20%E6%BC%A2%E5%AD%97%20%D8%B9%D8%B1%D8%A8%D9%8A%29 > > >> > Which when passed into your Signature Base String will get URL escaped > >> > again: > > >> > POST&http%3A%2F%2Fapi.twitter.com <http://2fapi.twitter.com/> > > >> %2F1%2Fstatuses%2Fupdate.xml&oauth_consumer_key%3Dri8JxYK2ddwSV5xIUfNNvQ%26 > >> > >> oauth_nonce%3DFt6p0YgKlI2Htdk3WLE4mthwQXVpWc9Nv9ApzoQKUg%26oauth_signature > >> > >> _method%3DHMAC-SHA1%26oauth_timestamp%3D1274362505%26oauth_token%3D1194769 > >> > >> 49-gF0B5O1Wwa2UqqIwopAhQtQVTzmfSIOSiHQS7Vf8%26oauth_version%3D1.0%26status > >> > >> %3DI%2520can%2520tweet%2520many%2520kinds%2520of%2520characters%2520%2521% > >> > >> 2520%2528%252A%2520%2524%2520%2540%2520%25E6%25BC%25A2%25E5%25AD%2597%2520 > >> %25D8%25B9%25D8%25B1%25D8%25A8%25D9%258A%2529 > > >> > The Content-Length for that fully-encoded POST body will be: 69 > > >> > And when Twitter spits the status back at you, in my case in XML: > >> > <?xml version="1.0" encoding="UTF-8"?> > >> > <status> > >> > <created_at>Thu May 20 13:35:04 +0000 2010</created_at> > >> > <id>14361447181</id> > >> > <text>I can tweet many kinds of characters ! (* $ @ 漢字 > >> > عربي)</text> > >> > <source><a href="http://realitytechnicians.com" > >> > rel="nofollow">Crying Indian</a></source> > >> > <truncated>false</truncated> > >> > <in_reply_to_status_id></in_reply_to_status_id> > >> > <in_reply_to_user_id></in_reply_to_user_id> > >> > <favorited>false</favorited> > >> > <in_reply_to_screen_name></in_reply_to_screen_name> > >> > <user> > >> > <id>119476949</id> > >> > <name>OAuth Dancer</name> > >> > <screen_name>oauth_dancer</screen_name> > >> > <location>San Francisco, CA</location> > >> > <description></description> > >> > <profile_image_url> > >>http://a3.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg > >> > </profile_image_url> > >> > <url>http://bit.ly/oauth-dancer</url> > >> > <protected>false</protected> > >> > <followers_count>11</followers_count> > >> > <profile_background_color>C0DEED</profile_background_color> > >> > <profile_text_color>333333</profile_text_color> > >> > <profile_link_color>0084B4</profile_link_color> > >> > <profile_sidebar_fill_color>DDEEF6</profile_sidebar_fill_color> > >> > <profile_sidebar_border_color>C0DEED</profile_sidebar_border_color> > >> > <friends_count>11</friends_count> > >> > <created_at>Wed Mar 03 19:37:35 +0000 2010</created_at> > >> > <favourites_count>0</favourites_count> > >> > <utc_offset></utc_offset> > >> > <time_zone></time_zone> > >> > <profile_background_image_url> > >>http://a3.twimg.com/profile_background_images/80151733/oauth-dance.png > >> > </profile_background_image_url> > >> > <profile_background_tile>true</profile_background_tile> > >> > <notifications>false</notifications> > >> > <geo_enabled>false</geo_enabled> > >> > <verified>false</verified> > >> > <following>false</following> > >> > <statuses_count>31</statuses_count> > >> > <lang>en</lang> > >> > <contributors_enabled>false</contributors_enabled> > >> > </user> > >> > <geo/> > >> > <coordinates/> > >> > <place/> > >> > <contributors/> > >> > </status> > > >> > Hope this helps. > > >> > TaylorOn Thu, May 20, 2010 at 5:03 AM, Onn E <onn.elbo...@gmail.com> > >> wrote: > >> > > Hi Taylor, > > >> > > I am using Curl to update status. > >> > > I use POST method. > >> > > The new status is not included in the headers, but is included in the > >> > > POST body and in the signature base string. > >> > > Also (and this Curl does automatically for me) I am sending the > >> > > following header: > >> > > Content-Type: application/x-www-form-urlencoded. > >> > > My new status value is URL encoded (UTF-8). > > >> > > And now to the business itself: > >> > > I know my signature method is correct since I am able to update single > >> > > word statuses with no special characters, such as: "hello", "ok", > >> > > "magnificent" and such. They work just fine. > >> > > But when trying to update statuses with characters such as: " ", "!", > >> > > "@". It will throw me with a 401: > >> > > {"request":"/1/statuses/update.json","error":"Incorrect > >> > > signature"} > > >> > > I'm attaching here the curl verbose: > > >> > > " > > >> > > curl -v -X POST -H 'Authorization: OAuth > >> > > oauth_nonce="5671352764895675466", oauth_signature_method="HMAC-SHA1", > >> > > oauth_timestamp="1274355202", oauth_consumer="**********************", > >> > > oauth_signature="**************************************", > >> > > oauth_version="1.0", > >> > > oauth_token="**************************************"' -d > >> > > "status=magnificent"https://api.twitter.com/1/statuses/update.json > >> > > * About to connect() to api.twitter.com port 443 (#0) > >> > > * Trying 128.242.240.61... connected > >> > > * Connected to api.twitter.com (128.242.240.61) port 443 (#0) > >> > > * successfully set certificate verify locations: > >> > > * CAfile: none > >> > > CApath: /etc/ssl/certs > >> > > * SSLv3, TLS handshake, Client hello (1): > >> > > * SSLv3, TLS handshake, Server hello (2): > >> > > * SSLv3,... > > read more »