Skip to content

Instantly share code, notes, and snippets.

@dmcquay
Created May 9, 2012 18:37
Show Gist options
  • Save dmcquay/2647830 to your computer and use it in GitHub Desktop.
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
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