aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorTom Christie2014-12-03 23:11:04 +0000
committerTom Christie2014-12-03 23:11:04 +0000
commitaf23ec36bbf4ccb8f4179e790b49b11677ccf6ee (patch)
tree7ea80a203cc8718150cd55e4403f3f4771160281 /rest_framework
parent3a5b3772fefc3c2f2c0899947cbc07bfe6e6b5d2 (diff)
parent0cc990792c63caa8fa8fea62cea53b0d28157b55 (diff)
downloaddjango-rest-framework-af23ec36bbf4ccb8f4179e790b49b11677ccf6ee.tar.bz2
Merge branch 'jpadilla-oauth_as_package' into version-3.1
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/authentication.py183
-rw-r--r--rest_framework/compat.py50
-rw-r--r--rest_framework/permissions.py28
3 files changed, 1 insertions, 260 deletions
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
index 36d74dd9..124ef68a 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -3,14 +3,9 @@ Provides various authentication policies.
"""
from __future__ import unicode_literals
import base64
-
from django.contrib.auth import authenticate
-from django.core.exceptions import ImproperlyConfigured
from django.middleware.csrf import CsrfViewMiddleware
-from django.conf import settings
from rest_framework import exceptions, HTTP_HEADER_ENCODING
-from rest_framework.compat import oauth, oauth_provider, oauth_provider_store
-from rest_framework.compat import oauth2_provider, provider_now, check_nonce
from rest_framework.authtoken.models import Token
@@ -178,181 +173,3 @@ class TokenAuthentication(BaseAuthentication):
def authenticate_header(self, request):
return 'Token'
-
-
-class OAuthAuthentication(BaseAuthentication):
- """
- OAuth 1.0a authentication backend using `django-oauth-plus` and `oauth2`.
-
- Note: The `oauth2` package actually provides oauth1.0a support. Urg.
- We import it from the `compat` module as `oauth`.
- """
- www_authenticate_realm = 'api'
-
- def __init__(self, *args, **kwargs):
- super(OAuthAuthentication, self).__init__(*args, **kwargs)
-
- if oauth is None:
- raise ImproperlyConfigured(
- "The 'oauth2' package could not be imported."
- "It is required for use with the 'OAuthAuthentication' class.")
-
- if oauth_provider is None:
- raise ImproperlyConfigured(
- "The 'django-oauth-plus' package could not be imported."
- "It is required for use with the 'OAuthAuthentication' class.")
-
- def authenticate(self, request):
- """
- Returns two-tuple of (user, token) if authentication succeeds,
- or None otherwise.
- """
- try:
- oauth_request = oauth_provider.utils.get_oauth_request(request)
- except oauth.Error as err:
- raise exceptions.AuthenticationFailed(err.message)
-
- if not oauth_request:
- return None
-
- oauth_params = oauth_provider.consts.OAUTH_PARAMETERS_NAMES
-
- found = any(param for param in oauth_params if param in oauth_request)
- missing = list(param for param in oauth_params if param not in oauth_request)
-
- if not found:
- # OAuth authentication was not attempted.
- return None
-
- if missing:
- # OAuth was attempted but missing parameters.
- msg = 'Missing parameters: %s' % (', '.join(missing))
- raise exceptions.AuthenticationFailed(msg)
-
- if not self.check_nonce(request, oauth_request):
- msg = 'Nonce check failed'
- raise exceptions.AuthenticationFailed(msg)
-
- try:
- consumer_key = oauth_request.get_parameter('oauth_consumer_key')
- consumer = oauth_provider_store.get_consumer(request, oauth_request, consumer_key)
- except oauth_provider.store.InvalidConsumerError:
- msg = 'Invalid consumer token: %s' % oauth_request.get_parameter('oauth_consumer_key')
- raise exceptions.AuthenticationFailed(msg)
-
- if consumer.status != oauth_provider.consts.ACCEPTED:
- msg = 'Invalid consumer key status: %s' % consumer.get_status_display()
- raise exceptions.AuthenticationFailed(msg)
-
- try:
- token_param = oauth_request.get_parameter('oauth_token')
- token = oauth_provider_store.get_access_token(request, oauth_request, consumer, token_param)
- except oauth_provider.store.InvalidTokenError:
- msg = 'Invalid access token: %s' % oauth_request.get_parameter('oauth_token')
- raise exceptions.AuthenticationFailed(msg)
-
- try:
- self.validate_token(request, consumer, token)
- except oauth.Error as err:
- raise exceptions.AuthenticationFailed(err.message)
-
- user = token.user
-
- if not user.is_active:
- msg = 'User inactive or deleted: %s' % user.username
- raise exceptions.AuthenticationFailed(msg)
-
- return (token.user, token)
-
- def authenticate_header(self, request):
- """
- If permission is denied, return a '401 Unauthorized' response,
- with an appropraite 'WWW-Authenticate' header.
- """
- return 'OAuth realm="%s"' % self.www_authenticate_realm
-
- def validate_token(self, request, consumer, token):
- """
- Check the token and raise an `oauth.Error` exception if invalid.
- """
- oauth_server, oauth_request = oauth_provider.utils.initialize_server_request(request)
- oauth_server.verify_request(oauth_request, consumer, token)
-
- def check_nonce(self, request, oauth_request):
- """
- Checks nonce of request, and return True if valid.
- """
- oauth_nonce = oauth_request['oauth_nonce']
- oauth_timestamp = oauth_request['oauth_timestamp']
- return check_nonce(request, oauth_request, oauth_nonce, oauth_timestamp)
-
-
-class OAuth2Authentication(BaseAuthentication):
- """
- OAuth 2 authentication backend using `django-oauth2-provider`
- """
- www_authenticate_realm = 'api'
- allow_query_params_token = settings.DEBUG
-
- def __init__(self, *args, **kwargs):
- super(OAuth2Authentication, self).__init__(*args, **kwargs)
-
- if oauth2_provider is None:
- raise ImproperlyConfigured(
- "The 'django-oauth2-provider' package could not be imported. "
- "It is required for use with the 'OAuth2Authentication' class.")
-
- def authenticate(self, request):
- """
- Returns two-tuple of (user, token) if authentication succeeds,
- or None otherwise.
- """
-
- auth = get_authorization_header(request).split()
-
- if len(auth) == 1:
- msg = 'Invalid bearer header. No credentials provided.'
- raise exceptions.AuthenticationFailed(msg)
- elif len(auth) > 2:
- msg = 'Invalid bearer header. Token string should not contain spaces.'
- raise exceptions.AuthenticationFailed(msg)
-
- if auth and auth[0].lower() == b'bearer':
- access_token = auth[1]
- elif 'access_token' in request.POST:
- access_token = request.POST['access_token']
- elif 'access_token' in request.GET and self.allow_query_params_token:
- access_token = request.GET['access_token']
- else:
- return None
-
- return self.authenticate_credentials(request, access_token)
-
- def authenticate_credentials(self, request, access_token):
- """
- Authenticate the request, given the access token.
- """
-
- try:
- token = oauth2_provider.oauth2.models.AccessToken.objects.select_related('user')
- # provider_now switches to timezone aware datetime when
- # the oauth2_provider version supports to it.
- token = token.get(token=access_token, expires__gt=provider_now())
- except oauth2_provider.oauth2.models.AccessToken.DoesNotExist:
- raise exceptions.AuthenticationFailed('Invalid token')
-
- user = token.user
-
- if not user.is_active:
- msg = 'User inactive or deleted: %s' % user.get_username()
- raise exceptions.AuthenticationFailed(msg)
-
- return (user, token)
-
- def authenticate_header(self, request):
- """
- Bearer is the only finalized type currently
-
- Check details on the `OAuth2Authentication.authenticate` method
- """
- return 'Bearer realm="%s"' % self.www_authenticate_realm
diff --git a/rest_framework/compat.py b/rest_framework/compat.py
index 5bd85e74..da2496d8 100644
--- a/rest_framework/compat.py
+++ b/rest_framework/compat.py
@@ -251,56 +251,6 @@ except ImportError:
etree = None
-# OAuth2 is optional
-try:
- # Note: The `oauth2` package actually provides oauth1.0a support. Urg.
- import oauth2 as oauth
-except ImportError:
- oauth = None
-
-
-# OAuthProvider is optional
-try:
- import oauth_provider
- from oauth_provider.store import store as oauth_provider_store
-
- # check_nonce's calling signature in django-oauth-plus changes sometime
- # between versions 2.0 and 2.2.1
- def check_nonce(request, oauth_request, oauth_nonce, oauth_timestamp):
- check_nonce_args = inspect.getargspec(oauth_provider_store.check_nonce).args
- if 'timestamp' in check_nonce_args:
- return oauth_provider_store.check_nonce(
- request, oauth_request, oauth_nonce, oauth_timestamp
- )
- return oauth_provider_store.check_nonce(
- request, oauth_request, oauth_nonce
- )
-
-except (ImportError, ImproperlyConfigured):
- oauth_provider = None
- oauth_provider_store = None
- check_nonce = None
-
-
-# OAuth 2 support is optional
-try:
- import provider as oauth2_provider
- from provider import scope as oauth2_provider_scope
- from provider import constants as oauth2_constants
- if oauth2_provider.__version__ in ('0.2.3', '0.2.4'):
- # 0.2.3 and 0.2.4 are supported version that do not support
- # timezone aware datetimes
- import datetime
- provider_now = datetime.datetime.now
- else:
- # Any other supported version does use timezone aware datetimes
- from django.utils.timezone import now as provider_now
-except ImportError:
- oauth2_provider = None
- oauth2_provider_scope = None
- oauth2_constants = None
- provider_now = None
-
# `seperators` argument to `json.dumps()` differs between 2.x and 3.x
# See: http://bugs.python.org/issue22767
if six.PY3:
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py
index 29f60d6d..7c498645 100644
--- a/rest_framework/permissions.py
+++ b/rest_framework/permissions.py
@@ -3,8 +3,7 @@ Provides a set of pluggable permission policies.
"""
from __future__ import unicode_literals
from django.http import Http404
-from rest_framework.compat import (get_model_name, oauth2_provider_scope,
- oauth2_constants)
+from rest_framework.compat import get_model_name
SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS']
@@ -199,28 +198,3 @@ class DjangoObjectPermissions(DjangoModelPermissions):
return False
return True
-
-
-class TokenHasReadWriteScope(BasePermission):
- """
- The request is authenticated as a user and the token used has the right scope
- """
-
- def has_permission(self, request, view):
- token = request.auth
- read_only = request.method in SAFE_METHODS
-
- if not token:
- return False
-
- if hasattr(token, 'resource'): # OAuth 1
- return read_only or not request.auth.resource.is_readonly
- elif hasattr(token, 'scope'): # OAuth 2
- required = oauth2_constants.READ if read_only else oauth2_constants.WRITE
- return oauth2_provider_scope.check(required, request.auth.scope)
-
- assert False, (
- 'TokenHasReadWriteScope requires either the'
- '`OAuthAuthentication` or `OAuth2Authentication` authentication '
- 'class to be used.'
- )