49👍
You can have multiple authentication backends. Just set the AUTHENTICATION_BACKENDS
in settings.py
of your Django project to list the backend implementations you want to use. For example I often use a combination of OpenID authentication and the standard Django authentication, like this in my settings.py
:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'django_openid_auth.auth.OpenIDBackend',
)
In this example Django will first try to authenticate using django.contrib.auth.backends.ModelBackend
, which is the default backend of Django. If that fails, then it moves on to the next backend, django_openid_auth.auth.OpenIDBackend
.
Note that your custom backends must be at a path visible by Django. In this example I have to add django_openid_auth
to INSTALLED_APPS
, otherwise Django won’t be able to import it and use it as a backend.
Also read the relevant documentation, it’s very nicely written, easy to understand:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/
9👍
I’ve been through this problem before. This is the code I used.
This is the authentication backend at the api/backend.py
from django.contrib.auth.models import User
class EmailOrUsernameModelBackend(object):
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
And this is my settings.py
AUTHENTICATION_BACKENDS = (
'api.backend.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
This code will enable you to use email to authenticate the default Django user even in Django admin.
- [Django]-Why won't Django use IPython?
- [Django]-Django: For Loop to Iterate Form Fields
- [Django]-How to pass django rest framework response to html?
2👍
Using multiple backend authentications is as simple as pie. You just need to understand the workflow of Django apps.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.Backend1',
'django_openid_auth.auth.Backend2',
)
For example you have the following two backends defined. Django will first go to the first backend and you just need to put some logic in that backend so that, if its not related to that backend it get forwarded to the other backend or returned without any results. In case of no results django will automatically shift the request from first backend to the second and if available third one.
I spend a lot of time on this and found out that it was not that complex.
- [Django]-Nginx doesn't serve static
- [Django]-How to pass django rest framework response to html?
- [Django]-Passing STATIC_URL to file javascript with django
1👍
Using Multiple AUTHENTICATION BACKENDS is very easy,
you just need to add this to settings.py
AUTHENTICATION_BACKENDS = (
'social_core.backends.open_id.OpenIdAuth',
'social_core.backends.google.GoogleOpenId',
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.google.GoogleOAuth',
'social_core.backends.facebook.FacebookOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
and this may create a problem at signup page so add a login argument in your signup view in views.py file like this
login(request, user, backend=’django.contrib.auth.backends.ModelBackend’)
def signup_view(request):
if request.method=='POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user=form.save()
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect('home')
- [Django]-Specifying limit and offset in Django QuerySet wont work
- [Django]-How do I install psycopg2 for Python 3.x?
- [Django]-How to pass django rest framework response to html?
0👍
Done a little safety and reassemble for code. cause provided solutions wasn’t perfectly matching necessary.
my version for the previous: https://stackoverflow.com/a/17078818/14972653
with my addition and @M.Void comment:
This is the authentication backend at the api/backend.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.core.validators import validate_email
user_model = get_user_model()
class EmailOrUsernameModelBackend(ModelBackend):
"""EmailOrUsernameModelBackend - UsernameOrEmail custom authentication backend
with email or username validation on same field
provides case insensitive validation of username and email
BEWARE - if you allow users to register two usernames in differren cases like: Alex and alex - there would be error.
still uses ModelBackend so provides permissions and is_active validation
"""
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(user_model.USERNAME_FIELD)
if username is None or password is None:
return
try:
validate_email(username)
except ValidationError as e:
kwargs = {'username__iexact': username} # remove __iexact to make it case sensitive
else:
kwargs = {'email__iexact': username} # remove __iexact to make it case sensitive
try:
user = user_model.objects.get(**kwargs)
except user_model.DoesNotExist:
return None
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
return user_model.objects.get(pk=user_id)
except user_model.DoesNotExist:
return None
and of course add it to your authentication backends:
AUTHENTICATION_BACKENDS = (
'api.backend.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
- [Django]-Specifying limit and offset in Django QuerySet wont work
- [Django]-Cannot access django app through ip address while accessing it through localhost
- [Django]-How do you detect a new instance of the model in Django's model.save()