Skip to content

Commit

Permalink
Merge remote-tracking branch 'eculver/master'
Browse files Browse the repository at this point in the history
Conflicts:
	.travis.yml
	requirements.txt
  • Loading branch information
flashingpumpkin committed Jan 16, 2013
2 parents 2359c4e + 1e20314 commit 8e38778
Show file tree
Hide file tree
Showing 20 changed files with 860 additions and 778 deletions.
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ install:
- pip install -q $DJANGO --use-mirrors
- pip install -q -r requirements.txt --use-mirrors
- python setup.py develop
branches:
only:
- master
- develop
script: tests/test.sh

2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
django-oauth2-provider
======================

.. image:: https://secure.travis-ci.org/caffeinehit/django-oauth2-provider.png
.. image:: https://secure.travis-ci.org/eculver/django-oauth2-provider.png?branch=develop

*django-oauth2-provider* is a Django application that provides
customizable OAuth2\_ authentication for your Django projects.
Expand Down
2 changes: 1 addition & 1 deletion example/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^oauth2/', include('provider.oauth2.urls', namespace = 'oauth2')),
url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
)
5 changes: 3 additions & 2 deletions provider/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
RESPONSE_TYPE_CHOICES = getattr(settings, 'OAUTH_RESPONSE_TYPE_CHOICES', ("code", "token"))

READ = 1 << 1
WRITE = 1 << 2
WRITE = 1 << 2
READ_WRITE = READ | WRITE

DEFAULT_SCOPES = (
(READ, 'read'),
(READ_WRITE, 'write'),
(WRITE, 'write'),
(READ_WRITE, 'read+write'),
)

SCOPES = getattr(settings, 'OAUTH_SCOPES', DEFAULT_SCOPES)
Expand Down
37 changes: 21 additions & 16 deletions provider/forms.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,53 @@
from django import forms


class OAuthValidationError(Exception):
"""
Exception to throw inside :class:`OAuthForm` if any OAuth2 related errors
are encountered such as invalid grant type, invalid client, etc.
:attr:`OAuthValidationError` expects a dictionary outlining the OAuth error
:attr:`OAuthValidationError` expects a dictionary outlining the OAuth error
as its first argument when instantiating.
:example:
::
class GrantValidationForm(OAuthForm):
grant_type = forms.CharField()
def clean_grant(self):
if not self.cleaned_data.get('grant_type') == 'code':
raise OAuthValidationError({
'error': 'invalid_grant',
'error': 'invalid_grant',
'error_description': "%s is not a valid grant type" % (
self.cleaned_data.get('grant_type'))
})
The different types of errors are outlined in :draft:`4.2.2.1` and :draft:`5.2`.
The different types of errors are outlined in :draft:`4.2.2.1` and
:draft:`5.2`.
"""


class OAuthForm(forms.Form):
"""
Form class that creates shallow error dicts and exists early when a
:class:`OAuthValidationError` is raised.
The shallow error dict is reused when returning error responses to the client.
The different types of errors are outlined in :draft:`4.2.2.1` and :draft:`5.2`.
:class:`OAuthValidationError` is raised.
The shallow error dict is reused when returning error responses to the
client.
The different types of errors are outlined in :draft:`4.2.2.1` and
:draft:`5.2`.
"""
def __init__(self, *args, **kwargs):
self.client = kwargs.pop('client', None)
super(OAuthForm, self).__init__(*args, **kwargs)

def _clean_fields(self):
"""
Overriding the default cleaning behaviour to exit early on errors instead
of validating each field.
Overriding the default cleaning behaviour to exit early on errors
instead of validating each field.
"""
try:
super(OAuthForm, self)._clean_fields()
Expand Down
12 changes: 7 additions & 5 deletions provider/oauth2/admin.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from django.contrib import admin
from provider.oauth2.models import AccessToken, Grant, Client, \
RefreshToken
from .models import AccessToken, Grant, Client, RefreshToken


class AccessTokenAdmin(admin.ModelAdmin):
list_display = ('user', 'client', 'token', 'expires', 'scope',)
raw_id_fields = ('user',)


class GrantAdmin(admin.ModelAdmin):
list_display = ('user', 'client', 'code', 'expires',)
raw_id_fields = ('user',)

class ClientAdmin(admin.ModelAdmin):


class ClientAdmin(admin.ModelAdmin):
list_display = ('url', 'user', 'redirect_uri', 'client_id', 'client_type')
raw_id_fields = ('user',)

Expand Down
37 changes: 20 additions & 17 deletions provider/oauth2/backends.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime
from provider.oauth2.forms import ClientAuthForm
from provider.oauth2.models import Client, AccessToken
from .forms import ClientAuthForm
from .models import AccessToken


class BaseBackend(object):
"""
Expand All @@ -14,28 +15,31 @@ def authenticate(self, request=None):
"""
pass


class BasicClientBackend(object):
"""
Backend that tries to authenticate a client through HTTP authorization headers
as defined in :draft:`2.3.1`.
Backend that tries to authenticate a client through HTTP authorization
headers as defined in :draft:`2.3.1`.
"""
def authenticate(self, request=None):
auth = request.META.get('HTTP_AUTHORIZATION')

if auth is None or auth == '':
return None

try:
basic, base64 = auth.split(' ')
client_id, client_secret = base64.decode('base64').split(':')

form = ClientAuthForm({'client_id': client_id, 'client_secret': client_secret})


form = ClientAuthForm({
'client_id': client_id,
'client_secret': client_secret})

if form.is_valid():
return form.cleaned_data.get('client')
return None

except ValueError, e:
except ValueError:
# Auth header was malformed, unpacking went wrong
return None

Expand All @@ -48,24 +52,23 @@ class RequestParamsClientBackend(object):
def authenticate(self, request=None):
if request is None:
return None

form = ClientAuthForm(request.REQUEST)

if form.is_valid():
return form.cleaned_data.get('client')

return None


class AccessTokenBackend(object):
"""
"""
Authenticate a user via access token and client object.
"""

def authenticate(self, access_token=None, client=None):
try:
return AccessToken.objects.get(token=access_token,
expires__gt=datetime.now(), client=client)
except AccessToken.DoesNotExist:
return None

Loading

0 comments on commit 8e38778

Please sign in to comment.