david / django-oauth (http://oauth.net/)
Support of OAuth in Django. Note that http://code.welldev.org/django-oauth-plus will use python-oauth2 if you're interested in it.
| commit 31: | 4f12d70ae49d |
| parent 30: | 95a6aab951cd |
| branch: | default |
Check callback's validity, comes from Toby White's fork, thanks.
12 months ago
django-oauth /
oauth_provider
/
stores.py
| # Introduced |
|---|
1 |
4f12d70ae49d |
from urlparse import urlparse |
2 |
4f12d70ae49d |
|
3 |
1c85c4505a4e |
from oauth.oauth import OAuthDataStore, OAuthError, escape |
4 |
c3ff630fbbb4 |
|
5 |
95a6aab951cd |
from models import Nonce, Token, Consumer, Resource, generate_random |
6 |
4f12d70ae49d |
from consts import VERIFIER_SIZE, MAX_URL_LENGTH |
7 |
c3ff630fbbb4 |
|
8 |
c3ff630fbbb4 |
|
9 |
1c85c4505a4e |
class DataStore(OAuthDataStore): |
10 |
c3ff630fbbb4 |
"""Layer between Python OAuth and Django database.""" |
11 |
e259c3486dd4 |
def __init__(self, oauth_request): |
12 |
c3ff630fbbb4 |
self.signature = oauth_request.parameters.get('oauth_signature', None) |
13 |
c3ff630fbbb4 |
self.timestamp = oauth_request.parameters.get('oauth_timestamp', None) |
14 |
c3ff630fbbb4 |
self.scope = oauth_request.parameters.get('scope', 'all') |
15 |
c3ff630fbbb4 |
|
16 |
c3ff630fbbb4 |
def lookup_consumer(self, key): |
17 |
c3ff630fbbb4 |
try: |
18 |
c3ff630fbbb4 |
self.consumer = Consumer.objects.get(key=key) |
19 |
c3ff630fbbb4 |
return self.consumer |
20 |
c3ff630fbbb4 |
except Consumer.DoesNotExist: |
21 |
c3ff630fbbb4 |
return None |
22 |
c3ff630fbbb4 |
|
23 |
c3ff630fbbb4 |
def lookup_token(self, token_type, token): |
24 |
c3ff630fbbb4 |
if token_type == 'request': |
25 |
c3ff630fbbb4 |
token_type = Token.REQUEST |
26 |
c3ff630fbbb4 |
elif token_type == 'access': |
27 |
c3ff630fbbb4 |
token_type = Token.ACCESS |
28 |
c3ff630fbbb4 |
try: |
29 |
c3ff630fbbb4 |
self.request_token = Token.objects.get(key=token, |
30 |
c3ff630fbbb4 |
token_type=token_type) |
31 |
c3ff630fbbb4 |
return self.request_token |
32 |
c3ff630fbbb4 |
except Token.DoesNotExist: |
33 |
c3ff630fbbb4 |
return None |
34 |
c3ff630fbbb4 |
|
35 |
c3ff630fbbb4 |
def lookup_nonce(self, oauth_consumer, oauth_token, nonce): |
36 |
e259c3486dd4 |
if oauth_token is None: |
37 |
c3ff630fbbb4 |
return None |
38 |
c3ff630fbbb4 |
nonce, created = Nonce.objects.get_or_create(consumer_key=oauth_consumer.key, |
39 |
c3ff630fbbb4 |
token_key=oauth_token.key, |
40 |
c3ff630fbbb4 |
key=nonce) |
41 |
c3ff630fbbb4 |
if created: |
42 |
c3ff630fbbb4 |
return None |
43 |
c3ff630fbbb4 |
else: |
44 |
c3ff630fbbb4 |
return nonce.key |
45 |
c3ff630fbbb4 |
|
46 |
c038f3e47c5f |
def fetch_request_token(self, oauth_consumer, oauth_callback): |
47 |
4f12d70ae49d |
if oauth_consumer.key != self.consumer.key: |
48 |
4f12d70ae49d |
raise OAuthError('Consumer key does not match.') |
49 |
4f12d70ae49d |
|
50 |
4f12d70ae49d |
# OAuth 1.0a: if there is a callback, check its validity |
51 |
4f12d70ae49d |
if oauth_callback and \ |
52 |
4f12d70ae49d |
not (oauth_callback == "oob" or check_valid_callback(oauth_callback)): |
53 |
4f12d70ae49d |
raise OAuthError('Invalid callback URL.') |
54 |
4f12d70ae49d |
|
55 |
4f12d70ae49d |
try: |
56 |
4f12d70ae49d |
resource = Resource.objects.get(name=self.scope) |
57 |
4f12d70ae49d |
except: |
58 |
4f12d70ae49d |
raise OAuthError('Resource %s does not exist.' % escape(self.scope)) |
59 |
4f12d70ae49d |
self.request_token = Token.objects.create_token(consumer=self.consumer, |
60 |
4f12d70ae49d |
token_type=Token.REQUEST, |
61 |
4f12d70ae49d |
timestamp=self.timestamp, |
62 |
4f12d70ae49d |
resource=resource) |
63 |
4f12d70ae49d |
# OAuth 1.0a: if there is a callback, set it |
64 |
4f12d70ae49d |
if oauth_callback: |
65 |
4f12d70ae49d |
self.request_token.set_callback(oauth_callback) |
66 |
4f12d70ae49d |
|
67 |
4f12d70ae49d |
return self.request_token |
68 |
4f12d70ae49d |
|
69 |
c3ff630fbbb4 |
|
70 |
c038f3e47c5f |
def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier): |
71 |
c3ff630fbbb4 |
if oauth_consumer.key == self.consumer.key \ |
72 |
c3ff630fbbb4 |
and oauth_token.key == self.request_token.key \ |
73 |
c3ff630fbbb4 |
and self.request_token.is_approved: |
74 |
95a6aab951cd |
# OAuth 1.0a: if there is a callback confirmed, check the verifier |
75 |
95a6aab951cd |
if (self.request_token.callback_confirmed \ |
76 |
95a6aab951cd |
and oauth_verifier == self.request_token.verifier) \ |
77 |
95a6aab951cd |
or not self.request_token.callback_confirmed: |
78 |
95a6aab951cd |
self.access_token = Token.objects.create_token(consumer=self.consumer, |
79 |
95a6aab951cd |
token_type=Token.ACCESS, |
80 |
95a6aab951cd |
timestamp=self.timestamp, |
81 |
95a6aab951cd |
user=self.request_token.user, |
82 |
95a6aab951cd |
resource=self.request_token.resource) |
83 |
95a6aab951cd |
return self.access_token |
84 |
95a6aab951cd |
raise OAuthError('Consumer key or token key does not match. ' \ |
85 |
95a6aab951cd |
+'Make sure your request token is approved. ' \ |
86 |
95a6aab951cd |
+'Check your verifier too if you use OAuth 1.0a.') |
87 |
c3ff630fbbb4 |
|
88 |
c3ff630fbbb4 |
def authorize_request_token(self, oauth_token, user): |
89 |
c3ff630fbbb4 |
if oauth_token.key == self.request_token.key: |
90 |
c3ff630fbbb4 |
# authorize the request token in the store |
91 |
c3ff630fbbb4 |
self.request_token.is_approved = True |
92 |
95a6aab951cd |
|
93 |
95a6aab951cd |
# OAuth 1.0a: if there is a callback confirmed, we must set a verifier |
94 |
95a6aab951cd |
if self.request_token.callback_confirmed: |
95 |
95a6aab951cd |
self.request_token.verifier = generate_random(VERIFIER_SIZE) |
96 |
95a6aab951cd |
|
97 |
c3ff630fbbb4 |
self.request_token.user = user |
98 |
c3ff630fbbb4 |
self.request_token.save() |
99 |
c3ff630fbbb4 |
return self.request_token |
100 |
1c85c4505a4e |
raise OAuthError('Token key does not match.') |
101 |
4f12d70ae49d |
|
102 |
4f12d70ae49d |
|
103 |
4f12d70ae49d |
def check_valid_callback(callback): |
104 |
4f12d70ae49d |
""" |
105 |
4f12d70ae49d |
Checks the size and nature of the callback. |
106 |
4f12d70ae49d |
""" |
107 |
4f12d70ae49d |
callback_url = urlparse(callback) |
108 |
4f12d70ae49d |
return (callback_url.scheme in ['http', 'https'] |
109 |
4f12d70ae49d |
and callback_url.hostname |
110 |
4f12d70ae49d |
and len(callback) < MAX_URL_LENGTH) |
