aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/authentication.py
diff options
context:
space:
mode:
authorTom Christie2012-09-20 13:06:27 +0100
committerTom Christie2012-09-20 13:06:27 +0100
commit4b691c402707775c3048a90531024f3bc5be6f91 (patch)
tree3adfc54b0d8b70e4ea78edf7091f7827fa68f47b /rest_framework/authentication.py
parenta1bcfbfe926621820832e32b0427601e1140b4f7 (diff)
downloaddjango-rest-framework-4b691c402707775c3048a90531024f3bc5be6f91.tar.bz2
Change package name: djangorestframework -> rest_framework
Diffstat (limited to 'rest_framework/authentication.py')
-rw-r--r--rest_framework/authentication.py132
1 files changed, 132 insertions, 0 deletions
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
new file mode 100644
index 00000000..fd597397
--- /dev/null
+++ b/rest_framework/authentication.py
@@ -0,0 +1,132 @@
+"""
+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.
+"""
+
+from django.contrib.auth import authenticate
+from rest_framework.compat import CsrfViewMiddleware
+from rest_framework.authtoken.models import Token
+import base64
+
+
+class BaseAuthentication(object):
+ """
+ All authentication classes should extend BaseAuthentication.
+ """
+
+ 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`.
+ """
+ return None
+
+
+class BasicAuthentication(BaseAuthentication):
+ """
+ Base class for HTTP Basic authentication.
+ Subclasses should implement `.authenticate_credentials()`.
+ """
+
+ def authenticate(self, request):
+ """
+ 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":
+ try:
+ auth_parts = base64.b64decode(auth[1]).partition(':')
+ except TypeError:
+ return None
+
+ try:
+ userid, password = smart_unicode(auth_parts[0]), smart_unicode(auth_parts[2])
+ except DjangoUnicodeDecodeError:
+ return None
+
+ return self.authenticate_credentials(userid, password)
+
+ 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)
+ if user is not None and user.is_active:
+ return (user, None)
+
+
+class SessionAuthentication(BaseAuthentication):
+ """
+ Use Django's session framework for authentication.
+ """
+
+ def authenticate(self, request):
+ """
+ Returns a :obj:`User` if the request session currently has a logged in user.
+ Otherwise returns :const:`None`.
+ """
+ user = getattr(request._request, 'user', None)
+
+ if user and user.is_active:
+ # Enforce CSRF validation for session based authentication.
+ resp = CsrfViewMiddleware().process_view(request, None, (), {})
+
+ if resp is None: # csrf passed
+ return (user, None)
+
+
+class TokenAuthentication(BaseAuthentication):
+ """
+ Simple token based authentication.
+
+ Clients should authenticate by passing the token key in the "Authorization"
+ HTTP header, prepended with the string "Token ". For example:
+
+ Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a
+ """
+
+ model = Token
+ """
+ A custom token model may be used, but must have the following properties.
+
+ * key -- The string identifying the token
+ * user -- The user to which the token belongs
+ """
+
+ def authenticate(self, request):
+ auth = request.META.get('HTTP_AUTHORIZATION', '').split()
+
+ if len(auth) == 2 and auth[0].lower() == "token":
+ key = auth[1]
+ try:
+ token = self.model.objects.get(key=key)
+ except self.model.DoesNotExist:
+ return None
+
+ if token.user.is_active and not getattr(token, 'revoked', False):
+ return (token.user, token)
+
+# TODO: OAuthAuthentication