June 18th, 2019
Django is one of the most famous Python frameworks. In this tutorial, I explain how to automatically log in users in its built-in admin interface using an LDAP.
Django provides a very useful admin interface that permits to manage users, display and modify model data. But have you ever tried to integrate a Django application in a big company?
I have and, most of the time, they already have an authentication system to authenticate their users. For example, 95% of Fortune 1000 companies use Active Directory from Microsoft to manage their users.
Therefore, the users are authenticated all over the network and there is no point adding the Django Admin login page with custom credentials. Not to mention the company security department that would probably not accept a different credential database.
Let’s see how we can automatically log in users with a concrete example!
Before creating our application, you need to install python and pip.
This article gives the installation details on Mac and Linux.
We will also need pipenv to create a contained environment and avoid conflicts with other projects (more details on why using pipenv).
You can install it with this command:
pip install pipenv —-user
The first step is to create our contained pipenv environment and install Django and ldap3, a library to connect to an LDAP:
mkdir DjangoApplications && cd DjangoApplications pipenv install Django ldap3
Now that we have a configured environment, we can create our Django application and initialize the database:
pipenv run django-admin startproject AutomaticDjangoAuthentication cd AutomaticDjangoAuthentication pipenv run python manage.py migrate
We have now a Django application called AutomaticDjangoAuthentication ready to be run.
Let’s launch it:
pipenv run python manage.py runserver
The application is launched and you should be able to access the admin dashboard on http://localhost:8000/admin:
By default, Django uses a user-oriented authentication with a login page. To connect on the admin dashboard and add other users, we need to create a user with all the permissions (super user) using the createsuperuser command:
pipenv run python manage.py createsuperuser
You should be able to connect using the user you created and access the admin dashboard.
We can now customize the default Django authentication process to authenticate using LDAP and auto-create the users in the Django database.
The default Django authentication uses backend classes to authenticate the users. On login, each backend authenticate method is called by priority until a user is returned or no more backends are to try.
In order to have an interesting external authentication system, I used a public LDAP server shared by forumsys. It provides several users and different groups that make LDAP tests very easy (more details here).
I created a service to check the user can authenticate in the LDAP given a username and password:
Then we can create our custom authentication backend. We check that the user can access the LDAP (or your own authentication system).
If so, we create and return a Django user with the permissions we want him to have. Here I give him only the right to access the admin dashboard (see Django permissions):
The last step before trying our new login is to override the default configuration. To do this, we add our backend in the Django app settings file settings.py:
With a single sign-on protocol implemented, like Kerberos in Active Directory, the users only have to log in once to be authenticated over the network. It is then not UX friendly to ask the users to log in another time.
To avoid that, we will use the Django middleware to automatically log in instead of displaying the login page.
Django uses several middlewares, which are defined with a priority in settings.py, to ensure security, cookies, authentication and more.
Each middleware is a layer wrapping the view that can implement five hooks. Each hook is a step to manage the request, display the view and manage the response and potential exceptions (more details in the Django documentation).
In the schema below you can see in which order the hooks are called in Django 1.7:
We will then add a new middleware after the AuthenticationMiddleware to automatically authenticate the users:
It is very basic!
We try to authenticate the user if he is not already authenticated. Then we either log in the user in the app or return a Forbidden response if the user cannot be authenticated.
As with the backend, we have to add the middleware to the Django configuration file settings.py:
To simplify this article, I did not implement a complex Kerberos server. Instead, I used query strings to pass the user’s credentials.
We must then modify our custom authentication backend to get the query strings from the request:
Now you can try to access the admin dashboard
And receive a 403 Forbidden! 🤯 (if you’re already logged in, log out and retry)
That’s because you need to send your credentials as query strings to be authenticated.
Let’s try again with http://localhost:8000/admin/?username=euler&password=password … Magic, it works 🎉
We can now authenticate each user without going through the login page.
A concrete implementation would not use query strings. Instead, we would use the external authentication system to get the users’ information. For example, I integrated this solution with Active Directory.
Active Directory is a Microsoft solution that uses the LDAP protocol and the Kerberos single sign-on protocol:
If you want to plug with an Active Directory Kerberos, you can follow this tutorial. Once you configured Apache, you will be able to access the user’s username in the request REMOTE_USER header.
With the username, you will then be able to fetch the user information from the Active Directory LDAP and create the user in the Django database.
In this article, I have shown how to use a custom authentication to automatically log in Django admin.
With this strategy, you avoid the implementation of a new authentication protocol and a complete copy of your existing database.
Furthermore, you can easily customize it with your own authentication system. You can also personalize the user experience by setting the user’s permissions using LDAP groups.
You can see, clone, fork the whole project on Github: AutomaticDjangoAuthentication, yannbriancon 👨🎓.
I hope this helped, feel free to comment 😎