Last active
December 20, 2015 22:59
-
-
Save ScottEAdams/6209642 to your computer and use it in GitHub Desktop.
Two similar ways for doing email based authentication for tastypie. Based on a mixture of BasicAuthentication and userena email login. Good for when using USERENA_WITHOUT_USERNAMES = True.
This file contains hidden or 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
import base64 | |
from django.contrib.auth import get_user_model, authenticate | |
from django.core.exceptions import ValidationError | |
from django.core.validators import validate_email | |
from tastypie.authentication import Authentication | |
from tastypie.http import HttpUnauthorized | |
class TastyEmailAuthentication(Authentication): | |
def __init__(self, realm='django-tastypie', **kwargs): | |
super(TastyEmailAuthentication, self).__init__(**kwargs) | |
self.realm = realm | |
def _unauthorized(self): | |
response = HttpUnauthorized() | |
# FIXME: Sanitize realm. | |
response['WWW-Authenticate'] = 'Basic Realm="%s"' % self.realm | |
return response | |
def is_authenticated(self, request, **kwargs): | |
""" | |
Checks a user's basic auth credentials using email address. | |
Should return either ``True`` if allowed, ``False`` if not or an | |
``HttpResponse`` if you need something custom. | |
""" | |
if not request.META.get('HTTP_AUTHORIZATION'): | |
return self._unauthorized() | |
try: | |
(auth_type, data) = request.META['HTTP_AUTHORIZATION'].split() | |
if auth_type.lower() != 'basic': | |
return self._unauthorized() | |
user_pass = base64.b64decode(data).decode('utf-8') | |
except: | |
return self._unauthorized() | |
bits = user_pass.split(':', 1) | |
if len(bits) != 2: | |
return self._unauthorized() | |
User = get_user_model() | |
try: | |
validate_email(bits[0]) | |
try: | |
user = User.objects.get(email__iexact=bits[0]) | |
if not self.check_active(user): | |
return False | |
if user.check_password(bits[1]): | |
request.user = user | |
return True | |
else: | |
return self._unauthorized() | |
except User.DoesNotExist: | |
return self._unauthorized() | |
except ValidationError: | |
return self._unauthorized() | |
class BasicEmailAuthentication(Authentication): | |
""" | |
Handles HTTP Basic auth against a specific auth backend if provided, | |
or against all configured authentication backends using the | |
``authenticate`` method from ``django.contrib.auth``. | |
Optional keyword arguments: | |
``backend`` | |
If specified, use a specific ``django.contrib.auth`` backend instead | |
of checking all backends specified in the ``AUTHENTICATION_BACKENDS`` | |
setting. | |
``realm`` | |
The realm to use in the ``HttpUnauthorized`` response. Default: | |
``django-tastypie``. | |
""" | |
def __init__(self, backend=None, realm='django-tastypie', **kwargs): | |
super(BasicEmailAuthentication, self).__init__(**kwargs) | |
self.backend = backend | |
self.realm = realm | |
def _unauthorized(self): | |
response = HttpUnauthorized() | |
# FIXME: Sanitize realm. | |
response['WWW-Authenticate'] = 'Basic Realm="%s"' % self.realm | |
return response | |
def is_authenticated(self, request, **kwargs): | |
""" | |
Checks a user's basic auth credentials against the current | |
Django auth backend. | |
Should return either ``True`` if allowed, ``False`` if not or an | |
``HttpResponse`` if you need something custom. | |
""" | |
if not request.META.get('HTTP_AUTHORIZATION'): | |
return self._unauthorized() | |
try: | |
(auth_type, data) = request.META['HTTP_AUTHORIZATION'].split() | |
if auth_type.lower() != 'basic': | |
return self._unauthorized() | |
user_pass = base64.b64decode(data).decode('utf-8') | |
except: | |
return self._unauthorized() | |
bits = user_pass.split(':', 1) | |
if len(bits) != 2: | |
return self._unauthorized() | |
User = get_user_model() | |
try: | |
validate_email(bits[0]) | |
try: | |
email_user = User.objects.get(email__iexact=bits[0]) | |
username = email_user.username | |
if self.backend: | |
user = self.backend.authenticate(username=username, password=bits[1]) | |
else: | |
user = authenticate(username=username, password=bits[1]) | |
if user is None: | |
return self._unauthorized() | |
if not self.check_active(user): | |
return False | |
request.user = user | |
return True | |
except User.DoesNotExist: | |
return self._unauthorized() | |
except ValidationError: | |
return self._unauthorized() | |
def get_identifier(self, request): | |
""" | |
Provides a unique string identifier for the requestor. | |
This implementation returns the user's basic auth username. | |
""" | |
return request.META.get('REMOTE_USER', 'nouser') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment