Question

I am trying to use Twitter OAuth and my POST requests are failing with a 401 (Invalid OAuth Request) error.

For example, if I want to post a new status update, I am sending a HTTP POST request to https://twitter.com/statuses/update.json with the following parameters -

status=Testing&oauth_version=1.0&oauth_token=xxx&
oauth_nonce=xxx&oauth_timestamp=xxx&oauth_signature=xxx&
oauth_consumer_key=xxx&in_reply_to=xxx&oauth_signature_method=HMAC-SHA1`

My GET requests are all working fine. I can see on the mailing lists that a lot of people have had identical problems but I could not find a solution anywhere.

I am using the oauth.py Python library.

Was it helpful?

Solution

Most likely, the signature is invalid. You must follow the OAuth spec on how to generate the signature( normalized parameters, URLencoding, and cosumerSecret&oauthScret. More on this later ......

OTHER TIPS

I just finished implementing twitter OAuth API from scratch using Java. Get and post requests work OK. You can use this page http://www.hueniverse.com/hueniverse/2008/10/beginners-gui-1.html to check signature and HTTP headers. Just enter your keys and tokens and check output. It seems twitter works exactly as described on this post. Be careful with spaces and UTF-8 symbols, for example Java encodes space as "+" but OAuth requires %20

Make sure your app access type is read & write. On your app settings page (ex. http://twitter.com/apps/edit/12345) there's a radio button field like this:

Default Access type: Read & Write / Read-only

If you check 'Read-only' then status update API will return 401.

I second the answer by Jrgns. I has exactly the same issue. When reading the example Twitter provides, it's actually clear. However their pseudo code is misleading. In Python this worked for me :

def encodekeyval(key, val):
    key = urllib.quote(key, '')
    val = urllib.quote(val, '')
    return urllib.quote(key + '=' + val, '')

def signature_base_string(urlstr, oauthdata):
    sigstr = 'POST&' + urllib.quote(urlstr,'') + '&'
    # retrieve "post" data as dictionary of name value pairs
    pdata = oauthdata.getpdata()
    # need to sort parameters
    pstr = '%26'.join([encodekeyval(key, pdata[key]) for key in sorted(pdata.keys())])
    return sigstr + pstr

I had the same issues, until I realised that the parameters need to be encoded twice for the base string. My GET requests all worked fine, but my POSTs, particularly status updates, failed. On a hunch I tried a POST without spaces in the status parameter, and it worked.

In PHP:

function encode($input) {
    return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
}

$query = array();
foreach($parameters as $name => $value) {
    $query[] = encode($name) . '=' .encode($value);
}
$base = encode(strtoupper($method)) . '&' .encode($norm_url) . '&' . 
encode(implode('&', $query));

Notice the encode function around the names and values of the parameters, and then around the whole query string. A Space should end up as %2520, not just %20.

I found the solution and it works for me, You must add the following paramters in the request header and it should look like following (c# code), donot use & sign, instead separate parameters by comma(,) sign. and you must add the word "OAuth" in the beginging.

httpWebRequest.Headers[System.Net.HttpRequestHeader.Authorization] = "OAuth oauth_consumer_key=\"hAnZFaPKxXnJqdfLhDikdw\", oauth_nonce=\"4729687\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1284821989\", oauth_token=\"17596307-KH9iUzqTxaoa5576VjILkERgUxcqExRyXkfb8AsXy\", oauth_version=\"1.0\", oauth_signature=\"p8f5WTObefG1N9%2b8AlBji1pg18A%3d\"";

and other parameters like 'status' should be written in the body of the request.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top