oauth 1.0a compat, outsourcing secret/verifier generation to django, updating a few oauth models
This commit is contained in:
Родитель
2a61bcefca
Коммит
b25314ac87
|
@ -101,7 +101,11 @@ def initialize_server_request(request):
|
|||
# request.META['CONTENT_TYPE'] == "application/x-www-form-urlencoded":
|
||||
params = dict(request.REQUEST.items())
|
||||
else:
|
||||
params = {}
|
||||
params = { }
|
||||
|
||||
# Seems that we want to put HTTP_AUTHORIZATION into 'Authorization'
|
||||
# for oauth.py to understand. Lovely.
|
||||
request.META['Authorization'] = request.META.get('HTTP_AUTHORIZATION', '')
|
||||
|
||||
oauth_request = oauth.OAuthRequest.from_request(
|
||||
request.method, request.build_absolute_uri(),
|
||||
|
@ -149,7 +153,7 @@ def oauth_request_token(request):
|
|||
def oauth_auth_view(request, token, callback, params):
|
||||
form = forms.OAuthAuthenticationForm(initial={
|
||||
'oauth_token': token.key,
|
||||
'oauth_callback': callback,
|
||||
'oauth_callback': token.get_callback_url() or callback,
|
||||
})
|
||||
|
||||
return render_to_response('piston/authorize_token.html',
|
||||
|
@ -171,7 +175,7 @@ def oauth_user_auth(request):
|
|||
callback = oauth_server.get_callback(oauth_request)
|
||||
except:
|
||||
callback = None
|
||||
|
||||
|
||||
if request.method == "GET":
|
||||
params = oauth_request.get_normalized_parameters()
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ class Emitter(object):
|
|||
if not handler:
|
||||
return { }
|
||||
|
||||
has = dir(handler)
|
||||
ret = dict()
|
||||
|
||||
for field in fields - Emitter.RESERVED_FIELDS:
|
||||
|
|
|
@ -23,7 +23,7 @@ class ModelForm(forms.ModelForm):
|
|||
|
||||
class OAuthAuthenticationForm(forms.Form):
|
||||
oauth_token = forms.CharField(widget=forms.HiddenInput)
|
||||
oauth_callback = forms.CharField(widget=forms.HiddenInput)
|
||||
oauth_callback = forms.CharField(widget=forms.HiddenInput, required=False)
|
||||
authorize_access = forms.BooleanField(required=True)
|
||||
csrf_signature = forms.CharField(widget=forms.HiddenInput)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import urllib, time
|
||||
import urllib, time, urlparse
|
||||
|
||||
# Django imports
|
||||
from django.db.models.signals import post_save, post_delete
|
||||
|
@ -13,6 +13,7 @@ from signals import consumer_post_save, consumer_post_delete
|
|||
|
||||
KEY_SIZE = 18
|
||||
SECRET_SIZE = 32
|
||||
VERIFIER_SIZE = 10
|
||||
|
||||
CONSUMER_STATES = (
|
||||
('pending', 'Pending'),
|
||||
|
@ -21,6 +22,9 @@ CONSUMER_STATES = (
|
|||
('rejected', 'Rejected')
|
||||
)
|
||||
|
||||
def generate_random(length=SECRET_SIZE):
|
||||
return User.objects.make_random_password(length=length)
|
||||
|
||||
class Nonce(models.Model):
|
||||
token_key = models.CharField(max_length=KEY_SIZE)
|
||||
consumer_key = models.CharField(max_length=KEY_SIZE)
|
||||
|
@ -58,11 +62,10 @@ class Consumer(models.Model):
|
|||
c.generate_random_codes()
|
||||
"""
|
||||
key = User.objects.make_random_password(length=KEY_SIZE)
|
||||
|
||||
secret = User.objects.make_random_password(length=SECRET_SIZE)
|
||||
secret = generate_random(SECRET_SIZE)
|
||||
|
||||
while Consumer.objects.filter(key__exact=key, secret__exact=secret).count():
|
||||
secret = User.objects.make_random_password(length=SECRET_SIZE)
|
||||
secret = generate_random(SECRET_SIZE)
|
||||
|
||||
self.key = key
|
||||
self.secret = secret
|
||||
|
@ -77,6 +80,7 @@ class Token(models.Model):
|
|||
|
||||
key = models.CharField(max_length=KEY_SIZE)
|
||||
secret = models.CharField(max_length=SECRET_SIZE)
|
||||
verifier = models.CharField(max_length=VERIFIER_SIZE)
|
||||
token_type = models.IntegerField(choices=TOKEN_TYPES)
|
||||
timestamp = models.IntegerField(default=long(time.time()))
|
||||
is_approved = models.BooleanField(default=False)
|
||||
|
@ -84,6 +88,9 @@ class Token(models.Model):
|
|||
user = models.ForeignKey(User, null=True, blank=True, related_name='tokens')
|
||||
consumer = models.ForeignKey(Consumer)
|
||||
|
||||
callback = models.CharField(max_length=255, null=True, blank=True)
|
||||
callback_confirmed = models.BooleanField(default=False)
|
||||
|
||||
objects = TokenManager()
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -92,23 +99,50 @@ class Token(models.Model):
|
|||
def to_string(self, only_key=False):
|
||||
token_dict = {
|
||||
'oauth_token': self.key,
|
||||
'oauth_token_secret': self.secret
|
||||
'oauth_token_secret': self.secret,
|
||||
'oauth_callback_confirmed': 'true',
|
||||
}
|
||||
|
||||
if self.verifier:
|
||||
token_dict.update({ 'oauth_verifier': self.verifier })
|
||||
|
||||
if only_key:
|
||||
del token_dict['oauth_token_secret']
|
||||
|
||||
return urllib.urlencode(token_dict)
|
||||
|
||||
def generate_random_codes(self):
|
||||
key = User.objects.make_random_password(length=KEY_SIZE)
|
||||
secret = User.objects.make_random_password(length=SECRET_SIZE)
|
||||
secret = generate_random(SECRET_SIZE)
|
||||
|
||||
while Token.objects.filter(key__exact=key, secret__exact=secret).count():
|
||||
secret = User.objects.make_random_password(length=SECRET_SIZE)
|
||||
secret = generate_random(SECRET_SIZE)
|
||||
|
||||
self.key = key
|
||||
self.secret = secret
|
||||
self.save()
|
||||
|
||||
# -- OAuth 1.0a stuff
|
||||
|
||||
def get_callback_url(self):
|
||||
if self.callback and self.verifier:
|
||||
# Append the oauth_verifier.
|
||||
parts = urlparse.urlparse(self.callback)
|
||||
scheme, netloc, path, params, query, fragment = parts[:6]
|
||||
if query:
|
||||
query = '%s&oauth_verifier=%s' % (query, self.verifier)
|
||||
else:
|
||||
query = 'oauth_verifier=%s' % self.verifier
|
||||
return urlparse.urlunparse((scheme, netloc, path, params,
|
||||
query, fragment))
|
||||
return self.callback
|
||||
|
||||
def set_callback(self, callback):
|
||||
if callback != "oob": # out of band, says "we can't do this!"
|
||||
self.callback = callback
|
||||
self.callback_confirmed = True
|
||||
self.save()
|
||||
|
||||
admin.site.register(Token)
|
||||
|
||||
# Attach our signals
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import oauth
|
||||
|
||||
from models import Nonce, Token, Consumer
|
||||
from models import generate_random, VERIFIER_SIZE
|
||||
|
||||
class DataStore(oauth.OAuthDataStore):
|
||||
"""Layer between Python OAuth and Django database."""
|
||||
|
@ -44,12 +45,17 @@ class DataStore(oauth.OAuthDataStore):
|
|||
self.request_token = Token.objects.create_token(consumer=self.consumer,
|
||||
token_type=Token.REQUEST,
|
||||
timestamp=self.timestamp)
|
||||
|
||||
if oauth_callback:
|
||||
self.request_token.set_callback(oauth_callback)
|
||||
|
||||
return self.request_token
|
||||
return None
|
||||
|
||||
def fetch_access_token(self, oauth_consumer, oauth_token, oauth_callback):
|
||||
def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier):
|
||||
if oauth_consumer.key == self.consumer.key \
|
||||
and oauth_token.key == self.request_token.key \
|
||||
and oauth_verifier == self.request_token.verifier \
|
||||
and self.request_token.is_approved:
|
||||
self.access_token = Token.objects.create_token(consumer=self.consumer,
|
||||
token_type=Token.ACCESS,
|
||||
|
@ -63,6 +69,7 @@ class DataStore(oauth.OAuthDataStore):
|
|||
# authorize the request token in the store
|
||||
self.request_token.is_approved = True
|
||||
self.request_token.user = user
|
||||
self.request_token.verifier = generate_random(VERIFIER_SIZE)
|
||||
self.request_token.save()
|
||||
return self.request_token
|
||||
return None
|
Загрузка…
Ссылка в новой задаче