Search code examples
pythonurllib2twitter-oauth

Bad authentication data on using twitter authentication headers


I have written a Python program for using OAuth. I am observing one issue while accessing service resources using access token (Twitter as an example).

I am able to successfully retrieve the access_token, but if I try to use access_token as Authorization header in twitter, it doesn't work. However, if I pass this as normal url parameters, then I get the desired results.

parameters_access_resource = [
        ('oauth_consumer_key', self.consumerKey),
        ('oauth_signature_method', 'HMAC-SHA1'),
        ('oauth_timestamp', self._timestamp),
        ('oauth_nonce', self._nonce),
        ('oauth_version', '1.0'),
        ('oauth_token', self._accessToken),
        ('oauth_signature', self._signature)
        ]

Below Method Works :

urlLink = "https://api.twitter.com/1.1/account/settings.json"
url = "?".join((urlLink, urllib.urlencode(parameters_access_resource)))
reqobj = urllib2.Request(url,data=[])
resp = urllib2.urlopen(reqobj)
print resp.read()

Problem :

As per Twitter documentation, the access_token should be passed as Authorization header, so I modified the code as below

headers = {
    "Accept": "*/*",
    "Connection": "close",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Content-Type" : "application/x-www-form-urlencoded",
    "Host" : "api.twitter.com",
    "Authorization" : self._getAuthorizationHeader(parameters_access_resource)
    }


def _getAuthorizationHeader(self,params):
    params = dict(params)
    sortedParams = {}
    sortedParams = collections.OrderedDict(sorted(params.items()))
    authHeader = (
    '%s="%s"' % (k, v) for k, v in sortedParams.iteritems())
    retval = "OAuth " + ', '.join(authHeader)
    return retval

url = "https://api.twitter.com/1.1/account/settings.json"
reqobj = urllib2.Request(url,data=[],headers=headers)
resp = urllib2.urlopen(reqobj)
print resp.read()

Following error is reported, I have tried different combinations, including using requests module but I am not able to figure out the problem.

{"errors":[{"code":215,"message":"Bad Authentication data."}]}

Can someone please guide me on how to resolve this issue.

P.S : I know there are lot of modules already available for this task, but I am writing this code for my learning purpose.


Solution

  • Found a solution, there was a problem in building header, I was not percent-encoding the values for Authentication header. Below code fixed the problem

    def _getAuthorizationHeader(self,params):
        params = dict(params)
        sortedParams = {}
        sortedParams = collections.OrderedDict(sorted(params.items()))
        authHeader = (
        '%s="%s"' % (k, self._url_encode(v)) for k, v in sortedParams.iteritems())
        retval = "OAuth " + ', '.join(authHeader)
        return retval
    
    def _url_encode(self,s):
        return urllib.quote(str(s),safe='')