diff options
| author | Tom Christie | 2011-04-29 14:32:56 +0100 | 
|---|---|---|
| committer | Tom Christie | 2011-04-29 14:32:56 +0100 | 
| commit | b358fbdbe9cbd4ce644c4b2c7b9b4cec0811e14e (patch) | |
| tree | 601e5576995809b74f914cafcee8a7a8cd9c6937 /djangorestframework/authentication.py | |
| parent | 93aa065fa92f64472a3ee80564020a81776be742 (diff) | |
| download | django-rest-framework-b358fbdbe9cbd4ce644c4b2c7b9b4cec0811e14e.tar.bz2 | |
More refactoring - move various less core stuff into utils etc
Diffstat (limited to 'djangorestframework/authentication.py')
| -rw-r--r-- | djangorestframework/authentication.py | 84 | 
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  | 
