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.

Clone this repository (size: 114.7 KB): HTTPS / SSH
$ hg clone http://code.welldev.org/django-oauth
    #   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)