Skip to content

Commit 01854ea

Browse files
author
leah.culver
committed
Python lib 1.0a support. Very basic and hurting for tests. Thanks and John L. Scarfone.
git-svn-id: https://oauth.googlecode.com/svn/code/python@1092 f7ae4463-c52f-0410-a7dc-93bad6e629e8
1 parent ced0c3f commit 01854ea

File tree

3 files changed

+92
-24
lines changed

3 files changed

+92
-24
lines changed

oauth/example/client.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def run_example():
9898
# get request token
9999
print '* Obtain a request token ...'
100100
pause()
101-
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url=client.request_token_url)
101+
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, callback=CALLBACK_URL, http_url=client.request_token_url)
102102
oauth_request.sign_request(signature_method_plaintext, consumer, None)
103103
print 'REQUEST (via headers)'
104104
print 'parameters: %s' % str(oauth_request.parameters)
@@ -107,24 +107,31 @@ def run_example():
107107
print 'GOT'
108108
print 'key: %s' % str(token.key)
109109
print 'secret: %s' % str(token.secret)
110+
print 'callback confirmed? %s' % str(token.callback_confirmed)
110111
pause()
111112

112113
print '* Authorize the request token ...'
113114
pause()
114-
oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token, callback=CALLBACK_URL, http_url=client.authorization_url)
115+
oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token, http_url=client.authorization_url)
115116
print 'REQUEST (via url query string)'
116117
print 'parameters: %s' % str(oauth_request.parameters)
117118
pause()
118119
# this will actually occur only on some callback
119120
response = client.authorize_token(oauth_request)
120121
print 'GOT'
121122
print response
123+
# sad way to get the verifier
124+
import urlparse, cgi
125+
query = urlparse.urlparse(response)[4]
126+
params = cgi.parse_qs(query, keep_blank_values=False)
127+
verifier = params['oauth_verifier'][0]
128+
print 'verifier: %s' % verifier
122129
pause()
123130

124131
# get access token
125132
print '* Obtain an access token ...'
126133
pause()
127-
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_url=client.access_token_url)
134+
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, verifier=verifier, http_url=client.access_token_url)
128135
oauth_request.sign_request(signature_method_plaintext, consumer, token)
129136
print 'REQUEST (via headers)'
130137
print 'parameters: %s' % str(oauth_request.parameters)
@@ -138,7 +145,7 @@ def run_example():
138145
# access some protected resources
139146
print '* Access protected resources ...'
140147
pause()
141-
parameters = {'file': 'vacation.jpg', 'size': 'original', 'oauth_callback': CALLBACK_URL} # resource specific params
148+
parameters = {'file': 'vacation.jpg', 'size': 'original'} # resource specific params
142149
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='POST', http_url=RESOURCE_URL, parameters=parameters)
143150
oauth_request.sign_request(signature_method_hmac_sha1, consumer, token)
144151
print 'REQUEST (via post body)'

oauth/example/server.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
REQUEST_TOKEN_URL = 'https://photos.example.net/request_token'
3232
ACCESS_TOKEN_URL = 'https://photos.example.net/access_token'
3333
AUTHORIZATION_URL = 'https://photos.example.net/authorize'
34+
CALLBACK_URL = 'http://printer.example.com/request_token_ready'
3435
RESOURCE_URL = 'http://photos.example.net/photos'
3536
REALM = 'http://photos.example.net/'
37+
VERIFIER = 'verifier'
3638

3739
# example store for one of each thing
3840
class MockOAuthDataStore(oauth.OAuthDataStore):
@@ -42,6 +44,7 @@ def __init__(self):
4244
self.request_token = oauth.OAuthToken('requestkey', 'requestsecret')
4345
self.access_token = oauth.OAuthToken('accesskey', 'accesssecret')
4446
self.nonce = 'nonce'
47+
self.verifier = VERIFIER
4548

4649
def lookup_consumer(self, key):
4750
if key == self.consumer.key:
@@ -51,6 +54,8 @@ def lookup_consumer(self, key):
5154
def lookup_token(self, token_type, token):
5255
token_attrib = getattr(self, '%s_token' % token_type)
5356
if token == token_attrib.key:
57+
## HACK
58+
token_attrib.set_callback(CALLBACK_URL)
5459
return token_attrib
5560
return None
5661

@@ -59,13 +64,17 @@ def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
5964
return self.nonce
6065
return None
6166

62-
def fetch_request_token(self, oauth_consumer):
67+
def fetch_request_token(self, oauth_consumer, oauth_callback):
6368
if oauth_consumer.key == self.consumer.key:
69+
if oauth_callback:
70+
# want to check here if callback is sensible
71+
# for mock store, we assume it is
72+
self.request_token.set_callback(oauth_callback)
6473
return self.request_token
6574
return None
6675

67-
def fetch_access_token(self, oauth_consumer, oauth_token):
68-
if oauth_consumer.key == self.consumer.key and oauth_token.key == self.request_token.key:
76+
def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier):
77+
if oauth_consumer.key == self.consumer.key and oauth_token.key == self.request_token.key and oauth_verifier == self.verifier:
6978
# want to check here if token is authorized
7079
# for mock store, we assume it is
7180
return self.access_token
@@ -131,18 +140,14 @@ def do_GET(self):
131140
try:
132141
# get the request token
133142
token = self.oauth_server.fetch_request_token(oauth_request)
134-
callback = self.oauth_server.get_callback(oauth_request)
143+
# authorize the token (kind of does nothing for now)
144+
token = self.oauth_server.authorize_token(token, None)
145+
token.set_verifier(VERIFIER)
135146
# send okay response
136147
self.send_response(200, 'OK')
137148
self.end_headers()
138149
# return the callback url (to show server has it)
139-
self.wfile.write('callback: %s' % callback)
140-
# authorize the token (kind of does nothing for now)
141-
token = self.oauth_server.authorize_token(token, None)
142-
self.wfile.write('\n')
143-
# return the token key
144-
token_key = urllib.urlencode({'oauth_token': token.key})
145-
self.wfile.write('token key: %s' % token_key)
150+
self.wfile.write(token.get_callback_url())
146151
except oauth.OAuthError, err:
147152
self.send_oauth_error(err)
148153
return

oauth/oauth.py

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ def generate_nonce(length=8):
6464
"""Generate pseudorandom number."""
6565
return ''.join([str(random.randint(0, 9)) for i in range(length)])
6666

67+
def generate_verifier(length=8):
68+
"""Generate pseudorandom number."""
69+
return ''.join([str(random.randint(0, 9)) for i in range(length)])
70+
6771

6872
class OAuthConsumer(object):
6973
"""Consumer of OAuth authentication.
@@ -79,7 +83,7 @@ def __init__(self, key, secret):
7983
self.key = key
8084
self.secret = secret
8185

82-
86+
8387
class OAuthToken(object):
8488
"""OAuthToken is a data type that represents an End User via either an access
8589
or request token.
@@ -90,14 +94,45 @@ class OAuthToken(object):
9094
"""
9195
key = None
9296
secret = None
97+
callback = None
98+
callback_confirmed = None
99+
verifier = None
93100

94101
def __init__(self, key, secret):
95102
self.key = key
96103
self.secret = secret
97104

105+
def set_callback(self, callback):
106+
self.callback = callback
107+
self.callback_confirmed = 'true'
108+
109+
def set_verifier(self, verifier=None):
110+
if verifier is not None:
111+
self.verifier = verifier
112+
else:
113+
self.verifier = generate_verifier()
114+
115+
def get_callback_url(self):
116+
if self.callback and self.verifier:
117+
# Append the oauth_verifier.
118+
parts = urlparse.urlparse(self.callback)
119+
scheme, netloc, path, params, query, fragment = parts[:6]
120+
if query:
121+
query = '%s&oauth_verifier=%s' % (query, self.verifier)
122+
else:
123+
query = 'oauth_verifier=%s' % self.verifier
124+
return urlparse.urlunparse((scheme, netloc, path, params,
125+
query, fragment))
126+
return self.callback
127+
98128
def to_string(self):
99-
return urllib.urlencode({'oauth_token': self.key,
100-
'oauth_token_secret': self.secret})
129+
data = {
130+
'oauth_token': self.key,
131+
'oauth_token_secret': self.secret,
132+
}
133+
if self.callback_confirmed is not None:
134+
data['oauth_callback_confirmed'] = self.callback_confirmed
135+
return urllib.urlencode(data)
101136

102137
def from_string(s):
103138
""" Returns a token from something like:
@@ -106,7 +141,12 @@ def from_string(s):
106141
params = cgi.parse_qs(s, keep_blank_values=False)
107142
key = params['oauth_token'][0]
108143
secret = params['oauth_token_secret'][0]
109-
return OAuthToken(key, secret)
144+
token = OAuthToken(key, secret)
145+
try:
146+
token.callback_confirmed = params['oauth_callback_confirmed'][0]
147+
except KeyError:
148+
pass # 1.0, no callback confirmed.
149+
return token
110150
from_string = staticmethod(from_string)
111151

112152
def __str__(self):
@@ -124,6 +164,7 @@ class OAuthRequest(object):
124164
- oauth_timestamp
125165
- oauth_nonce
126166
- oauth_version
167+
- oauth_verifier
127168
... any additional parameters, as defined by the Service Provider.
128169
"""
129170
parameters = None # OAuth parameters.
@@ -258,7 +299,8 @@ def from_request(http_method, http_url, headers=None, parameters=None,
258299
from_request = staticmethod(from_request)
259300

260301
def from_consumer_and_token(oauth_consumer, token=None,
261-
http_method=HTTP_METHOD, http_url=None, parameters=None):
302+
callback=None, verifier=None, http_method=HTTP_METHOD,
303+
http_url=None, parameters=None):
262304
if not parameters:
263305
parameters = {}
264306

@@ -274,6 +316,12 @@ def from_consumer_and_token(oauth_consumer, token=None,
274316

275317
if token:
276318
parameters['oauth_token'] = token.key
319+
parameters['oauth_callback'] = token.callback
320+
# 1.0a support for verifier.
321+
parameters['oauth_verifier'] = verifier
322+
elif callback:
323+
# 1.0a support for callback in the request token request.
324+
parameters['oauth_callback'] = callback
277325

278326
return OAuthRequest(http_method, http_url, parameters)
279327
from_consumer_and_token = staticmethod(from_consumer_and_token)
@@ -348,9 +396,13 @@ def fetch_request_token(self, oauth_request):
348396
# No token required for the initial token request.
349397
version = self._get_version(oauth_request)
350398
consumer = self._get_consumer(oauth_request)
399+
try:
400+
callback = self.get_callback(oauth_request)
401+
except OAuthError:
402+
callback = None # 1.0, no callback specified.
351403
self._check_signature(oauth_request, consumer, None)
352404
# Fetch a new token.
353-
token = self.data_store.fetch_request_token(consumer)
405+
token = self.data_store.fetch_request_token(consumer, callback)
354406
return token
355407

356408
def fetch_access_token(self, oauth_request):
@@ -359,10 +411,11 @@ def fetch_access_token(self, oauth_request):
359411
"""
360412
version = self._get_version(oauth_request)
361413
consumer = self._get_consumer(oauth_request)
414+
verifier = self._get_verifier(oauth_request)
362415
# Get the request token.
363416
token = self._get_token(oauth_request, 'request')
364417
self._check_signature(oauth_request, consumer, token)
365-
new_token = self.data_store.fetch_access_token(consumer, token)
418+
new_token = self.data_store.fetch_access_token(consumer, token, verifier)
366419
return new_token
367420

368421
def verify_request(self, oauth_request):
@@ -429,6 +482,9 @@ def _get_token(self, oauth_request, token_type='access'):
429482
if not token:
430483
raise OAuthError('Invalid %s token: %s' % (token_type, token_field))
431484
return token
485+
486+
def _get_verifier(self, oauth_request):
487+
return oauth_request.get_parameter('oauth_verifier')
432488

433489
def _check_signature(self, oauth_request, consumer, token):
434490
timestamp, nonce = oauth_request._get_timestamp_nonce()
@@ -509,11 +565,11 @@ def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
509565
"""-> OAuthToken."""
510566
raise NotImplementedError
511567

512-
def fetch_request_token(self, oauth_consumer):
568+
def fetch_request_token(self, oauth_consumer, oauth_callback):
513569
"""-> OAuthToken."""
514570
raise NotImplementedError
515571

516-
def fetch_access_token(self, oauth_consumer, oauth_token):
572+
def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier):
517573
"""-> OAuthToken."""
518574
raise NotImplementedError
519575

0 commit comments

Comments
 (0)