Inspired by a discussion in the How to Extend Django User Model comments, I decided to compile a few options on how to implement a case insensitive authentication using the built in Django User. Thanks to Paul Spiteri for bringing up the question and also to provide a possible solution!
Option 1: Extending The User Model
This is the best option if your project is in the beginning and you can afford swapping the authentication User.
Actually any of the strategies described in the How to Extend Django User Model
will work (except for the Proxy model, because the AUTH_USER_MODEL
can’t be a Proxy).
Below, the most basic way to implement it, without messing around with anything:
models.py
Now, it’s just a matter of swapping the AUTH_USER_MODEL
in the settings.py module:
settings.py
And that’s it!
Option 2: Custom Authentication Backend
Please note that there is a small difference in the implementation between Django 1.10 and 1.11, as from 1.11 the
authenticate
method receives a request
object.
Django Version 1.10.x Or Below
If your application is already up and running and you can’t afford to customize the Django User model, this is the less intrusive way.
Create a python module named backends.py anywhere in your project and add the following snippet:
backends.py
Now switch the authentication backend in the settings.py module:
settings.py
Please note that 'mysite.core.backends.CaseInsensitiveModelBackend'
must be changed to the valid path, where you
created the backends.py module.
Django Version 1.11.x Or Higher
If your application is already up and running and you can’t afford to customize the Django User model, this is the less intrusive way.
Create a python module named backends.py anywhere in your project and add the following snippet:
backends.py
Now switch the authentication backend in the settings.py module:
settings.py
Please note that 'mysite.core.backends.CaseInsensitiveModelBackend'
must be changed to the valid path, where you
created the backends.py module.
Drawbacks
This change only affects the authentication process, it doesn’t enforce the uniqueness of the case insensitive
username. Meaning that you can still have a username saved as John
and another one as john
and another one as
JOHN
. Actually if that’s the case, the application will crash when John
or JOHN
try to authenticate in the
system, because UserModel._default_manager.get()
will return more than one row, and will eventually throw an
exception.
First thing you want to do, before you change the authentication backends, is to make sure there is no conflicting usernames in the database (same username with mixed case).
If you are good to go, make sure every input where the end user can set the username
field is properly validated.
For example, if you are using the built-in UserCreationForm
from django.contrib.auth.forms
, extend it and enforce
the validation. Below, a very straightforward example:
forms.py
The whole idea behind this strategy is to take care of all the possible ways the end user has to set the username, either by creating a new user or by editing it. Use it with caution.
I hope this tutorial could help you somehow!
Know a better way to solve this issue? Any questions? Comments? Leave a message in the comments below!