开发者

Google OAuth problem: invalid_signature

I'm trying to get OAuth working in a small Python script. I'm using python-oauth2, and I'm trying to connect to Google to list my Google docs.

Getting the request token and authorizing the token appear to work fine, but whenever I try to get the access token, I get an HTTP 400 response, and the response content is "signature_invalid".

Here's my code:

import httplib2, os, sys, tempfile, urllib, urlparse
import oauth2 as oauth
#httplib2.debuglevel=1

# this php script writes oauth_verifier to /tmp/verifier.txt
oauth_callback = 'http://localhost/api.php'

scope = 'https://docs.google.com/feeds/'
xoauth_displayname = 'Adam\'s API Test'
url = 'https://www.google.com/accounts/OAuthGetRequestToken?scope=%s&oauth_callback=%s&xoauth_displayname=%s' % (scope, oauth_callback, xoauth_displayname)

######## OAUTH: GET REQUEST TOKEN #############
consumer = oauth.Consumer('anonymous','anonymous')
client = oauth.Client(consumer)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
    print 'OAuthGetRequestToken OK'
else:
    print 'OAuthGetRequestToken status: %s' % resp['status']
    print content
    sys.exit(1)

######## OAUTH: AUTHORIZE TOKEN ###############
oauth_token = urlparse.parse_qs(content)['oauth_token'][0]
url = 'https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&oauth_token=%s' % urllib.quote_plus(oauth_token)
print 'Visit this URL in your browser: %s' % url
raw_input('Press ENTER once you have granted access...')

######## OAUTH: GET ACCESS TOKEN 开发者_StackOverflow社区##############
verifier = file('/tmp/verifier.txt').read().rstrip()
url = 'https://www.google.com/accounts/OAuthGetAccessToken?oauth_token=%s&oauth_verifier=%s' % (oauth_token, verifier)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
    print 'OAuthGetAccessToken OK'
    print content
else:
    print 'OAuthGetAccessToken status: %s' % resp['status']
    print content
    sys.exit(1)

Any ideas?


With Eva's help, I fixed it! This post had the solution.

I failed to utilize oauth_token_secret, returned from the original request for an unauthorized token. I missed that the Consumer was being reused, but a new Client was being instantiated for the access token fetch at the end of the Twitter Three-legged OAuth Example in the python-oauth2 README.

Here's the patch to fix the above code:

--- old.py  2011-07-28 10:38:06.904639958 -0500
+++ new.py  2011-07-28 10:38:44.192639954 -0500
@@ -22,6 +22,7 @@

 ######## OAUTH: AUTHORIZE TOKEN ###############
 oauth_token = urlparse.parse_qs(content)['oauth_token'][0]
+oauth_token_secret = urlparse.parse_qs(content)['oauth_token_secret'][0]
 url = 'https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&oauth_token=%s' % urllib.quote_plus(oauth_token)
 print 'Visit this URL in your browser: %s' % url
 raw_input('Press ENTER once you have granted access...')
@@ -29,6 +30,7 @@
 ######## OAUTH: GET ACCESS TOKEN ##############
 verifier = file('/tmp/verifier.txt').read().rstrip()
 url = 'https://www.google.com/accounts/OAuthGetAccessToken?oauth_token=%s&oauth_verifier=%s' % (oauth_token, verifier)
+client.token = oauth.Token(oauth_token, oauth_token_secret)
 resp, content = client.request(url, 'GET')
 if resp['status'] == '200':
     print 'OAuthGetAccessToken OK'

And here's the original code, with that patch applied:

import httplib2, os, sys, tempfile, urllib, urlparse
import oauth2 as oauth
#httplib2.debuglevel=1

# this php script writes oauth_verifier to /tmp/verifier.txt
oauth_callback = 'http://localhost/api.php'

scope = 'https://docs.google.com/feeds/'
xoauth_displayname = 'Adam\'s API Test'
url = 'https://www.google.com/accounts/OAuthGetRequestToken?scope=%s&oauth_callback=%s&xoauth_displayname=%s' % (scope, oauth_callback, xoauth_displayname)

######## OAUTH: GET REQUEST TOKEN #############
consumer = oauth.Consumer('anonymous','anonymous')
client = oauth.Client(consumer)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
    print 'OAuthGetRequestToken OK'
else:
    print 'OAuthGetRequestToken status: %s' % resp['status']
    print content
    sys.exit(1)

######## OAUTH: AUTHORIZE TOKEN ###############
oauth_token = urlparse.parse_qs(content)['oauth_token'][0]
oauth_token_secret = urlparse.parse_qs(content)['oauth_token_secret'][0]
url = 'https://www.google.com/accounts/OAuthAuthorizeToken?hd=default&oauth_token=%s' % urllib.quote_plus(oauth_token)
print 'Visit this URL in your browser: %s' % url
raw_input('Press ENTER once you have granted access...')

######## OAUTH: GET ACCESS TOKEN ##############
verifier = file('/tmp/verifier.txt').read().rstrip()
url = 'https://www.google.com/accounts/OAuthGetAccessToken?oauth_token=%s&oauth_verifier=%s' % (oauth_token, verifier)
client.token = oauth.Token(oauth_token, oauth_token_secret)
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
    print 'OAuthGetAccessToken OK'
    print content
else:
    print 'OAuthGetAccessToken status: %s' % resp['status']
    print content
    sys.exit(1)

Note that, actually, oauth_token and oauth_verifier do not need to be manually added to the query string for fetching the access token (python-oauth2 does that for us). I left the code as-is so I could illustrate the simplest change from the non-working code in the original post to the working code in this answer. The final URL can be simply https://www.google.com/accounts/OAuthGetAccessToken.

The final printed content spits out oauth_token and oauth_token_secret. These parameters are used in subsequent API calls, such as fetching a list of documents on Google Docs.

Here's example code to do that:

import httplib2, os, sys, tempfile, urllib, urlparse
import oauth2 as oauth

######## OAUTH: GET REQUEST TOKEN #############
consumer = oauth.Consumer('anonymous', 'anonymous')
creds = {'oauth_token_secret': 'INSERT_SECRET_FROM_ABOVE', 'oauth_token': 'INSERT_TOKEN_FROM_ABOVE'}
client = oauth.Client(consumer)
client.token = oauth.Token(creds['oauth_token'], creds['oauth_token_secret'])
url = 'https://docs.google.com/feeds/default/private/full?v=3'
resp, content = client.request(url, 'GET')
if resp['status'] == '200':
    print 'list status OK'
    fh = open('/tmp/list.xml', 'w')
    fh.write(content)
    fh.close()
else:
    print 'list status: %s' % resp['status']
    print content
    sys.exit(1)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜