How to debug 401 error in Twitter OAuth?


Hi, I’m trying to implement sign in via Twitter button on my website using Python, following this flow:

The problem is that I’m getting 401 error no matter what upon the very first request to endpoint.

I have the button “Allow this application to sign in with Twitter” enabled:

I also tried to debug this in OAuth Tool by getting a raw curl request from its signature-generator, but there seems to be a flaw in OAuth Tool, cause it would always include “oauth_token” parameter and calculate the signature with it, which is wrong, cause “request_token” endpoint shouldn’t accept this parameter.

So, how do I debug it?

Just in case, here is my source code for Django:

def twitter_oauth_submit_button_view(request):


    urlencode = urllib.quote_plus

    nonce = make_nonce()
    timestamp = int(time.time())
    # encode with client secret, NOTE the ampersand sign added to secret! Ampersand comes from the fact, that encoding key
    # should normally be "TWITTER_CLIENT_SECRET&OAUTH_TOKEN_SECRET", but as we don't have OAUTH_TOKEN_SECRET yet, we should
    # use just "TWITTER_CLIENT_SECRET&".
    # also note the urlencode() around TWITTER_CLIENT_SECRET

    hmaced ="&", make_basestring(nonce=nonce, timestamp=timestamp), sha1)
    signature = hmaced.digest().encode("base64").rstrip("\n")

    oauth_header = ('OAuth ' + 
                   'oauth_callback="' + urlencode('') + '", ' +
                   'oauth_consumer_key="' + urlencode(TWITTER_CLIENT_SECRET) + '", ' +                   
                   'oauth_nonce="' + urlencode(nonce) + '", ' +
                   'oauth_signature="' + urlencode(signature) + '", ' +
                   'oauth_signature_method="' + urlencode('HMAC-SHA1') + '", ' +
                   'oauth_timestamp="' + urlencode(str(timestamp)) + '", ' +

    headers = {'Authorization': oauth_header}
    r ="", headers=headers, data={})
    return HttpResponseRedirect("" %["auth_token"])

def make_basestring(nonce, timestamp, request_type="POST", url=""):
    urlencode = urllib.quote_plus

    params = [("oauth_callback", ''),
              ("oauth_consumer_key", settings.TWITTER_CLIENT_ID),
              ("oauth_nonce", nonce),
              ("oauth_signature_method", "HMAC-SHA1"),
              ("oauth_timestamp", str(timestamp)),
              ("oauth_version", "1.0")]
    oauth_params_string = "&".join([(urlencode(key) + "=" + urlencode(value)) for key, value in params])
    base_string = urlencode(request_type) + "&" + urlencode(url) + "&" + urlencode(oauth_params_string)
    return base_string

def make_nonce(length=32, charset='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
    return "".join([choice(charset) for i in range(length)])

My basestring is:


My Authentication header is:

OAuth oauth_callback="", oauth_consumer_key="7HoVWmsICqmRAGQJCym4OESn6qbhZm9XCvg9AjRcVKM3MG71s1", oauth_nonce="6EzEITZAfuVEPaVjIBMK3GV54K18Gk3k", oauth_signature="JLLLrJ75SUsfxjTqBsIQCGaZkRM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1417604435", oauth_version="1.0"


Sorry, guys! After 3 days of pain, I found the error in the very first lines of code: I’m sending TWITTER_CLIENT_SECRET instead of TWITTER_CLIENT_ID and, moreover, mistakingly assigned TWITTER_CLIENT_ID to the value of settings.TWITTER_CLIENT_SECRET. Now it works!

Still, I think, Twitter devs could make an option in Twitter OAuth Tool signature generator not to send the OAUTH_TOKEN with request, cause now it’s impossible to troubleshoot this first step with it.