Created
May 9, 2012 18:37
-
-
Save dmcquay/2647830 to your computer and use it in GitHub Desktop.
Tastypie MultiAuthentication configurable to require all to pass or just one to pass
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from tastypie.http import HttpUnauthorized | |
class MultiAuthentication(object): | |
""" | |
An authentication backend that tries a number of backends in order. You may specify using the and_ kwarg | |
whether or not all backends must authenticate the user or if authentication should stop after the first success. | |
It defaults to False, meaning that only one authentication backend must return True. | |
For example, let's say you have three classes: | |
MyAuth1 | |
MyAuth2 | |
MyAuth3 | |
The following will return true if either MyAuth1 or MyAuth2 returns True. | |
MultiAuthentication(MyAuth1(), MyAuth2()) | |
This will return true only if both return True. | |
MultiAuthentication(MyAuth1(), MyAuth2(), and_=True) | |
You can also nest them to create more complicated combinations. | |
Here we will require that MyAuth1 returns True and that either MyAuth2 or MyAuth3 return True. | |
MultiAuthentication( | |
MyAuth1(), | |
MultiAuthentication(MyAuth2(), MyAuth3()), | |
and_=True, | |
) | |
""" | |
def __init__(self, *backends, **kwargs): | |
self.backends = backends | |
self.and_ = kwargs.get('and_', False) | |
def is_authenticated(self, request, **kwargs): | |
""" | |
Identifies if the user is authenticated to continue or not. | |
Should return either ``True`` if allowed, ``False`` if not or an | |
``HttpResponse`` if you need something custom. | |
""" | |
try: | |
request._authentication_backend | |
except AttributeError: | |
request._authentication_backend = None | |
if self.and_: | |
for backend in self.backends: | |
check = backend.is_authenticated(request, **kwargs) | |
if not check or isinstance(check, HttpUnauthorized): | |
return check | |
else: | |
request._authentication_backend = request._authentication_backend or backend | |
return True | |
else: | |
unauthorized = False | |
for backend in self.backends: | |
check = backend.is_authenticated(request, **kwargs) | |
if check: | |
if isinstance(check, HttpUnauthorized): | |
unauthorized = unauthorized or check | |
else: | |
request._authentication_backend = request._authentication_backend or backend | |
return check | |
return unauthorized | |
def get_identifier(self, request): | |
""" | |
Provides a unique string identifier for the requestor. | |
This implementation returns a combination of IP address and hostname. | |
""" | |
try: | |
return request._authentication_backend.get_identifier(request) | |
except AttributeError: | |
return 'nouser' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment