aboutsummaryrefslogtreecommitdiffstats
path: root/djangorestframework/authentication.py
diff options
context:
space:
mode:
Diffstat (limited to 'djangorestframework/authentication.py')
-rw-r--r--djangorestframework/authentication.py84
1 files changed, 84 insertions, 0 deletions
diff --git a/djangorestframework/authentication.py b/djangorestframework/authentication.py
new file mode 100644
index 00000000..894b34fc
--- /dev/null
+++ b/djangorestframework/authentication.py
@@ -0,0 +1,84 @@
+"""The :mod:`authentication` modules provides for pluggable authentication behaviour.
+
+Authentication behaviour is provided by adding the mixin class :class:`AuthenticatorMixin` to a :class:`.Resource` or Django :class:`View` class.
+
+The set of authentication which are use is then specified by setting the :attr:`authentication` attribute on the class, and listing a set of authentication classes.
+"""
+from django.contrib.auth import authenticate
+from django.middleware.csrf import CsrfViewMiddleware
+from djangorestframework.utils import as_tuple
+import base64
+
+
+class BaseAuthenticator(object):
+ """All authentication should extend BaseAuthenticator."""
+
+ def __init__(self, view):
+ """Initialise the authentication with the mixin instance as state,
+ in case the authentication needs to access any metadata on the mixin object."""
+ self.view = view
+
+ def authenticate(self, request):
+ """Authenticate the request and return the authentication context or None.
+
+ An authentication context might be something as simple as a User object, or it might
+ be some more complicated token, for example authentication tokens which are signed
+ against a particular set of permissions for a given user, over a given timeframe.
+
+ The default permission checking on Resource will use the allowed_methods attribute
+ for permissions if the authentication context is not None, and use anon_allowed_methods otherwise.
+
+ The authentication context is available to the method calls eg Resource.get(request)
+ by accessing self.auth in order to allow them to apply any more fine grained permission
+ checking at the point the response is being generated.
+
+ This function must be overridden to be implemented."""
+ return None
+
+
+class BasicAuthenticator(BaseAuthenticator):
+ """Use HTTP Basic authentication"""
+ def authenticate(self, request):
+ 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:
+ uname, passwd = smart_unicode(auth_parts[0]), smart_unicode(auth_parts[2])
+ except DjangoUnicodeDecodeError:
+ return None
+
+ user = authenticate(username=uname, password=passwd)
+ if user is not None and user.is_active:
+ return user
+ return None
+
+
+class UserLoggedInAuthenticator(BaseAuthenticator):
+ """Use Django's built-in request session for authentication."""
+ def authenticate(self, request):
+ if getattr(request, 'user', None) and request.user.is_active:
+ # If this is a POST request we enforce CSRF validation.
+ if request.method.upper() == 'POST':
+ # Temporarily replace request.POST with .RAW_CONTENT,
+ # so that we use our more generic request parsing
+ request._post = self.view.RAW_CONTENT
+ resp = CsrfViewMiddleware().process_view(request, None, (), {})
+ del(request._post)
+ if resp is not None: # csrf failed
+ return None
+ return request.user
+ return None
+
+
+#class DigestAuthentication(BaseAuthentication):
+# pass
+#
+#class OAuthAuthentication(BaseAuthentication):
+# pass