diff options
Diffstat (limited to 'rest_framework/authentication.py')
| -rw-r--r-- | rest_framework/authentication.py | 62 |
1 files changed, 26 insertions, 36 deletions
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py index ee5bd2f2..30c78ebc 100644 --- a/rest_framework/authentication.py +++ b/rest_framework/authentication.py @@ -1,10 +1,10 @@ """ -The :mod:`authentication` module provides a set of pluggable authentication classes. - -Authentication behavior is provided by mixing the :class:`mixins.RequestMixin` class into a :class:`View` class. +Provides a set of pluggable authentication policies. """ from django.contrib.auth import authenticate +from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError +from rest_framework import exceptions from rest_framework.compat import CsrfViewMiddleware from rest_framework.authtoken.models import Token import base64 @@ -17,25 +17,14 @@ class BaseAuthentication(object): def authenticate(self, request): """ - Authenticate the :obj:`request` and return a :obj:`User` or :const:`None`. [*]_ - - .. [*] The authentication context *will* typically be a :obj:`User`, - but it need not be. It can be any user-like object so long as the - permissions classes (see the :mod:`permissions` module) on the view can - handle the object and use it to determine if the request has the required - permissions or not. - - This can be an important distinction if you're implementing some token - based authentication mechanism, where the authentication context - may be more involved than simply mapping to a :obj:`User`. + Authenticate the request and return a two-tuple of (user, token). """ - return None + raise NotImplementedError(".authenticate() must be overridden.") class BasicAuthentication(BaseAuthentication): """ - Base class for HTTP Basic authentication. - Subclasses should implement `.authenticate_credentials()`. + HTTP Basic authentication against username/password. """ def authenticate(self, request): @@ -43,8 +32,6 @@ class BasicAuthentication(BaseAuthentication): Returns a `User` if a correct username and password have been supplied using HTTP Basic authentication. Otherwise returns `None`. """ - from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError - if 'HTTP_AUTHORIZATION' in request.META: auth = request.META['HTTP_AUTHORIZATION'].split() if len(auth) == 2 and auth[0].lower() == "basic": @@ -54,7 +41,8 @@ class BasicAuthentication(BaseAuthentication): return None try: - userid, password = smart_unicode(auth_parts[0]), smart_unicode(auth_parts[2]) + userid = smart_unicode(auth_parts[0]) + password = smart_unicode(auth_parts[2]) except DjangoUnicodeDecodeError: return None @@ -62,15 +50,6 @@ class BasicAuthentication(BaseAuthentication): def authenticate_credentials(self, userid, password): """ - Given the Basic authentication userid and password, authenticate - and return a user instance. - """ - raise NotImplementedError('.authenticate_credentials() must be overridden') - - -class UserBasicAuthentication(BasicAuthentication): - def authenticate_credentials(self, userid, password): - """ Authenticate the userid and password against username and password. """ user = authenticate(username=userid, password=password) @@ -85,20 +64,31 @@ class SessionAuthentication(BaseAuthentication): def authenticate(self, request): """ - Returns a :obj:`User` if the request session currently has a logged in user. - Otherwise returns :const:`None`. + Returns a `User` if the request session currently has a logged in user. + Otherwise returns `None`. """ # Get the underlying HttpRequest object http_request = request._request user = getattr(http_request, 'user', None) - if user and user.is_active: - # Enforce CSRF validation for session based authentication. - resp = CsrfViewMiddleware().process_view(http_request, None, (), {}) + # Unauthenticated, CSRF validation not required + if not user or not user.is_active: + return + + # Enforce CSRF validation for session based authentication. + class CSRFCheck(CsrfViewMiddleware): + def _reject(self, request, reason): + # Return the failure reason instead of an HttpResponse + return reason + + reason = CSRFCheck().process_view(http_request, None, (), {}) + if reason: + # CSRF failed, bail with explicit error message + raise exceptions.PermissionDenied('CSRF Failed: %s' % reason) - if resp is None: # csrf passed - return (user, None) + # CSRF passed with authenticated user + return (user, None) class TokenAuthentication(BaseAuthentication): |
