Reputation: 153
That django authenticate function accepts two parameters, eg
user = authenticate(username=username, password=password)
, but I would like to pass in an additional parameter to validate the entry. Is that possible to do so or can the authenticate function be overridden to achieve that?
Please advise, thanks.
Upvotes: 2
Views: 1569
Reputation: 918
As far as I know, the authenticate()
function takes any keyword arguments as credentials. It simply forwards the credentials to the configured authentication backends. So it really depends on the authentication backend what you do with the passed arguments.
This means you can pass whatever you want to the authenticate()
function, but you might need to implement your own authentication backend. You can achieve that by specyfing custom auth backends in the settings.py
:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'confirm.django.auth.backends.EmailBackend',
)
Here's the code for the EmailBackend
:
from django.contrib.auth.backends import ModelBackend, UserModel
class EmailBackend(ModelBackend): # pylint: disable=too-few-public-methods
'''
Authentication backend class which authenticates the user against his
e-mail address instead of his username.
'''
def authenticate(self, username=None, password=None, **kwargs): # pylint: disable=unused-argument
'''
Authenticate the user via his e-mail address.
:param str username: The username used to authenticate
:param str password: The password used to authenticate
:return: When successful, the User model is returned
:rtype: User model or None
'''
try:
user = UserModel.objects.get(email=username)
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
return None
When a user is logging in with an e-mail address, the credentials will be passed to the ModelBackend.authenticate()
method, which will fail because there's no username matching the e-mail address. After that, the EmailBackend.authenticate()
method is called, which will succeed (if the password matches). The first backend returning a User
instance "wins".
So it depends what you want to do.
If you simply want to allow users logging in with either their username or e-mail address (or any other field), then this is the way to go. Just create a new auth backend and add it to the AUTHENTICATION_BACKENDS
, together with django.contrib.auth.backends.ModelBackend
.
If you need an additional field verified for the login, let's say a triplet like customer ID
, username
& password
, you need to create your own backend as well. However, this time the backend should be the only one configured in the AUTHENTICATION_BACKENDS
, thus replacing django.contrib.auth.backends.ModelBackend
with it.
If you want to know more about customizing authentication, just head over to the brilliant docs.
Upvotes: 1
Reputation: 811
authenticate is just a python function you can use *args & **kwargs to pass multiple params and you can override the authenticate method like (How to override authenticate method ) to add your own validation there.
Upvotes: 1