2011-05-10 13:49:28 +04:00
|
|
|
"""
|
|
|
|
The ``authentication`` module provides a set of pluggable authentication classes.
|
2011-02-19 16:12:35 +03:00
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
Authentication behavior is provided by adding the ``AuthMixin`` class to a ``View`` .
|
2011-02-19 16:12:35 +03:00
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
The set of authentication methods which are used is then specified by setting
|
|
|
|
``authentication`` attribute on the ``View`` class, and listing a set of authentication classes.
|
2011-02-19 16:12:35 +03:00
|
|
|
"""
|
2011-05-10 13:49:28 +04:00
|
|
|
|
2011-01-24 21:59:23 +03:00
|
|
|
from django.contrib.auth import authenticate
|
2011-02-19 13:26:27 +03:00
|
|
|
from django.middleware.csrf import CsrfViewMiddleware
|
|
|
|
from djangorestframework.utils import as_tuple
|
2011-01-24 21:59:23 +03:00
|
|
|
import base64
|
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
__all__ = (
|
|
|
|
'BaseAuthenticaton',
|
|
|
|
'BasicAuthenticaton',
|
|
|
|
'UserLoggedInAuthenticaton'
|
|
|
|
)
|
2011-02-19 13:26:27 +03:00
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
|
|
|
|
class BaseAuthenticaton(object):
|
|
|
|
"""
|
|
|
|
All authentication classes should extend BaseAuthentication.
|
|
|
|
"""
|
2011-01-24 21:59:23 +03:00
|
|
|
|
2011-04-25 04:03:23 +04:00
|
|
|
def __init__(self, view):
|
2011-05-10 13:49:28 +04:00
|
|
|
"""
|
|
|
|
Authentication classes are always passed the current view on creation.
|
|
|
|
"""
|
2011-04-25 04:03:23 +04:00
|
|
|
self.view = view
|
2011-01-24 21:59:23 +03:00
|
|
|
|
|
|
|
def authenticate(self, request):
|
2011-05-10 13:49:28 +04:00
|
|
|
"""
|
|
|
|
Authenticate the request and return a ``User`` instance or None. (*)
|
2011-02-19 13:26:27 +03:00
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
This function must be overridden to be implemented.
|
2011-01-24 21:59:23 +03:00
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
(*) The authentication context _will_ typically be a ``User`` object,
|
|
|
|
but it need not be. It can be any user-like object so long as the
|
|
|
|
permissions classes 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 ``User``.
|
|
|
|
"""
|
2011-01-24 21:59:23 +03:00
|
|
|
return None
|
|
|
|
|
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
class BasicAuthenticaton(BaseAuthenticaton):
|
|
|
|
"""
|
|
|
|
Use HTTP Basic authentication.
|
|
|
|
"""
|
|
|
|
|
2011-01-24 21:59:23 +03:00
|
|
|
def authenticate(self, request):
|
2011-04-05 05:40:18 +04:00
|
|
|
from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError
|
|
|
|
|
2011-01-24 21:59:23 +03:00
|
|
|
if 'HTTP_AUTHORIZATION' in request.META:
|
|
|
|
auth = request.META['HTTP_AUTHORIZATION'].split()
|
|
|
|
if len(auth) == 2 and auth[0].lower() == "basic":
|
2011-04-05 05:40:18 +04:00
|
|
|
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
|
|
|
|
|
2011-01-24 21:59:23 +03:00
|
|
|
user = authenticate(username=uname, password=passwd)
|
|
|
|
if user is not None and user.is_active:
|
|
|
|
return user
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
class UserLoggedInAuthenticaton(BaseAuthenticaton):
|
|
|
|
"""
|
|
|
|
Use Django's session framework for authentication.
|
|
|
|
"""
|
|
|
|
|
2011-01-24 21:59:23 +03:00
|
|
|
def authenticate(self, request):
|
2011-05-10 13:49:28 +04:00
|
|
|
# TODO: Switch this back to request.POST, and let MultiPartParser deal with the consequences.
|
2011-04-04 12:19:49 +04:00
|
|
|
if getattr(request, 'user', None) and request.user.is_active:
|
2011-04-27 00:08:36 +04:00
|
|
|
# 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
|
2011-04-27 21:44:21 +04:00
|
|
|
request._post = self.view.RAW_CONTENT
|
2011-04-27 00:08:36 +04:00
|
|
|
resp = CsrfViewMiddleware().process_view(request, None, (), {})
|
|
|
|
del(request._post)
|
|
|
|
if resp is not None: # csrf failed
|
|
|
|
return None
|
|
|
|
return request.user
|
2011-01-24 21:59:23 +03:00
|
|
|
return None
|
2011-04-27 21:07:28 +04:00
|
|
|
|
|
|
|
|
2011-05-10 13:49:28 +04:00
|
|
|
# TODO: TokenAuthentication, DigestAuthentication, OAuthAuthentication
|