@@ -64,6 +64,10 @@ def generate_nonce(length=8):
64
64
"""Generate pseudorandom number."""
65
65
return '' .join ([str (random .randint (0 , 9 )) for i in range (length )])
66
66
67
+ def generate_verifier (length = 8 ):
68
+ """Generate pseudorandom number."""
69
+ return '' .join ([str (random .randint (0 , 9 )) for i in range (length )])
70
+
67
71
68
72
class OAuthConsumer (object ):
69
73
"""Consumer of OAuth authentication.
@@ -79,7 +83,7 @@ def __init__(self, key, secret):
79
83
self .key = key
80
84
self .secret = secret
81
85
82
-
86
+
83
87
class OAuthToken (object ):
84
88
"""OAuthToken is a data type that represents an End User via either an access
85
89
or request token.
@@ -90,14 +94,45 @@ class OAuthToken(object):
90
94
"""
91
95
key = None
92
96
secret = None
97
+ callback = None
98
+ callback_confirmed = None
99
+ verifier = None
93
100
94
101
def __init__ (self , key , secret ):
95
102
self .key = key
96
103
self .secret = secret
97
104
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
+
98
128
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 )
101
136
102
137
def from_string (s ):
103
138
""" Returns a token from something like:
@@ -106,7 +141,12 @@ def from_string(s):
106
141
params = cgi .parse_qs (s , keep_blank_values = False )
107
142
key = params ['oauth_token' ][0 ]
108
143
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
110
150
from_string = staticmethod (from_string )
111
151
112
152
def __str__ (self ):
@@ -124,6 +164,7 @@ class OAuthRequest(object):
124
164
- oauth_timestamp
125
165
- oauth_nonce
126
166
- oauth_version
167
+ - oauth_verifier
127
168
... any additional parameters, as defined by the Service Provider.
128
169
"""
129
170
parameters = None # OAuth parameters.
@@ -258,7 +299,8 @@ def from_request(http_method, http_url, headers=None, parameters=None,
258
299
from_request = staticmethod (from_request )
259
300
260
301
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 ):
262
304
if not parameters :
263
305
parameters = {}
264
306
@@ -274,6 +316,12 @@ def from_consumer_and_token(oauth_consumer, token=None,
274
316
275
317
if token :
276
318
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
277
325
278
326
return OAuthRequest (http_method , http_url , parameters )
279
327
from_consumer_and_token = staticmethod (from_consumer_and_token )
@@ -348,9 +396,13 @@ def fetch_request_token(self, oauth_request):
348
396
# No token required for the initial token request.
349
397
version = self ._get_version (oauth_request )
350
398
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.
351
403
self ._check_signature (oauth_request , consumer , None )
352
404
# Fetch a new token.
353
- token = self .data_store .fetch_request_token (consumer )
405
+ token = self .data_store .fetch_request_token (consumer , callback )
354
406
return token
355
407
356
408
def fetch_access_token (self , oauth_request ):
@@ -359,10 +411,11 @@ def fetch_access_token(self, oauth_request):
359
411
"""
360
412
version = self ._get_version (oauth_request )
361
413
consumer = self ._get_consumer (oauth_request )
414
+ verifier = self ._get_verifier (oauth_request )
362
415
# Get the request token.
363
416
token = self ._get_token (oauth_request , 'request' )
364
417
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 )
366
419
return new_token
367
420
368
421
def verify_request (self , oauth_request ):
@@ -429,6 +482,9 @@ def _get_token(self, oauth_request, token_type='access'):
429
482
if not token :
430
483
raise OAuthError ('Invalid %s token: %s' % (token_type , token_field ))
431
484
return token
485
+
486
+ def _get_verifier (self , oauth_request ):
487
+ return oauth_request .get_parameter ('oauth_verifier' )
432
488
433
489
def _check_signature (self , oauth_request , consumer , token ):
434
490
timestamp , nonce = oauth_request ._get_timestamp_nonce ()
@@ -509,11 +565,11 @@ def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
509
565
"""-> OAuthToken."""
510
566
raise NotImplementedError
511
567
512
- def fetch_request_token (self , oauth_consumer ):
568
+ def fetch_request_token (self , oauth_consumer , oauth_callback ):
513
569
"""-> OAuthToken."""
514
570
raise NotImplementedError
515
571
516
- def fetch_access_token (self , oauth_consumer , oauth_token ):
572
+ def fetch_access_token (self , oauth_consumer , oauth_token , oauth_verifier ):
517
573
"""-> OAuthToken."""
518
574
raise NotImplementedError
519
575
0 commit comments