Invalid or expired token. in Python callback

oauth
python

#1

I am trying to create a Python oauth system to post tweets on behalf of a user. My initial page takes the user through the ‘Authorize XXX to use your account?’ dialog, then to a callback that is below.

If I print base_string, signature.digest().encode(“base64”).rstrip(’\n’), and auth_header they look like they are at least formatted right in reference to the Twitter Oauth example.

Am I somehow using the wrong key/secrets or something?

#!/usr/bin/python
print("Content-type: text/html\n")
#slightly modified version of http://www.programmableweb.com/news/how-to-build-twitter-hello-world-web-app-python/how-to/2015/06/16?page=3
import oauth2, urlparse, flask, hmac, hashlib, urllib, urllib3, certifi
import random
import time

import cgi
form = cgi.FieldStorage()

oauth_token = form.getvalue("oauth_token").strip()
oauth_verifier = form.getvalue("oauth_verifier").strip()
print('oauth_token ='+str(oauth_token) )

# Set the consumer key and secret
CONSUMER_KEY="consumer key from Application Settings"
CONSUMER_SECRET="consumer secret from Application Settings"

screen_name='username'
url='https://api.twitter.com/1.1/statuses/update.json'
status="Hello World @%s!" % screen_name
manager = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())

# Set the parameters required to build the base of the signature, using a dictionary for convenience
parameters = {
    "include_entities":"true",
    "oauth_consumer_key": CONSUMER_KEY,
    "oauth_nonce":  hashlib.sha1(str(random.random)).hexdigest(),
    "oauth_signature_method": "HMAC-SHA1",
    "oauth_timestamp": str(int(time.time())),
    "oauth_token": oauth_token,
    "oauth_version": "1.0",
    "status": status
}

# Build the string that forms the base of the signature, iterating through the dictionary and using the key/values in the string
method = "POST"
base_string = "%s&%s&%s" % (method,urllib.quote(url,""),urllib.quote('&'.join(sorted("%s=%s" % (key,value)
            for key,value in parameters.iteritems())),""))

# Create the signature using signing key composed of consumer secret and token secret obtained during 3-legged dance
qt = urllib.quote(oauth_token,"")
key1 = urllib.quote(CONSUMER_SECRET,"")+"&"+qt
signature = hmac.new(key1,
            base_string,hashlib.sha1)

# Add result to parameters and create a string in required format for header
parameters['oauth_signature'] = signature.digest().encode("base64").rstrip('\n')

auth_header = 'OAuth %s' % ', '.join(sorted('%s="%s"' % (urllib.quote(key,""),urllib.quote(value,""))
            for key,value in parameters.iteritems() if key != 'status'))

# Set HTTP headers
http_headers={"Authorization": auth_header, 'Content-Type': 'application/x-www-form-urlencoded'}

# Send the request
response = manager.urlopen("POST", url, headers=http_headers,body=status)

# Set messages that will be used in modal dialogs
if response.status == 200:
    print("Tweet sent mentioning @%s" % screen_name)
else:
    print("Error sending tweet: %s" % response.data)

#2

Upon callback from Twitter you only have a request token, you then have to exchange that for an access token using POST oauth/access_token. That token is then authorized to perform actions on the users account.