LogoEjk

emilkhatib.com

Authentication with Django REST Framework

April 17, 2016

This will be the last entry on the Simpsons quote search engine. In this entry we will add authentication; so the users of the REST API will need to have an account in order to use it.

This will be the last entry on the Simpsons quote search engine. In this entry we will add authentication; so the users of the REST API will need to have an account in order to use it. This will slightly change our communication protocol, since we will first have to authenticate.


By adding authentication, we can control not only the access to the application, but also what does each user get to see. We can, for instance, implement user profiles and sessions, and create applications such as chats, social networks or personalized data storage. Anyway, in this example, we will just limit the access to the system, and we won’t be managing the session.

Django and the REST Framework provide several authentication methods, such as simple authentication, OAuth, etc, but here, we will use token authentication, where each user gets a token that is used each time when a request is performed. This should always be used with HTTPS instead of normal HTTP. We will not be using HTTPS in this example, but it is very well explained here.


The first step we must do is to tell the REST Framework to use token authetication and to protect the API by default. We will edit the SQProject/settings.py file and find the REST_FRAMEWORK variable. We will change it to the following values:

REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), }


Next, we must add the necessary application to the project. This will let the REST Framework manage the tokens for the users. In the same file, we find the list of installed applications:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'SQapp', 'rest_framework', 'rest_framework.authtoken' ]


Each user will have an assigned token; nevertheless, the token may not be easy to remember or practical; and it must change with every session, so we also want to be able to identify with the system with the usual method of a username and password. The REST Framework provides this function by default in the installed authtoken application. In order to access the application, we must modify SQProject/urls.py. We must first import the view:

from rest_framework.authtoken.views import obtain_auth_token

and then in the URL list add the entry for authentication:

url(r'^api-token-auth/', obtain_auth_token)


We then update the database with

python manage.py migrate python manage.py makemigrations

If we try to use the API now with cURL, it will fail with the following message:

{"detail":"Authentication credentials were not provided."}


Now we must create the users. First, we will need a superuser in order to access to the Django administration interface. For that, we must execute python manage.py createsuperuser.

Once created, we launch a web browser and access http://localhost:8000/admin/.


Here we can create more users and then add a token for them.
In a production system, a specific view for creating users must be implemented, as well as session management to create the tokens before sending them to the users and manage access to the elements.


With the users and the tokens in the system, we can now query the API for the token with cURL:

curl -d "username=<user>&password=<pass>" localhost:8000/api-token-auth/

It will return a JSON string with the token:

{"token":"<key>"}


And with the token, we can now use the API again:

curl -d "terms=<search terms>" localhost:8000/search/ -H 'Authorization: Token <key>'

What we have created here is a good starting point for the backbone of a data-based application. This application will have several types of clients, adapted to different platforms (mobile, desktop, web …), that will use the commands we have been using with cURL. Most programming languages have the appropriate libraries for this. For instance, if we are accessing from an Android app, we can use the Android Asynchronous Http Client, or XMLHttpRequest in a JavaScript application. Similarly, Python has Requests.

One additional point that we have left out of this series on Django is the use of production servers. We have always used the builtin test server, which is not adequate for production. We must use servers such as Apache or Nginx.

There are many other things to discuss on Django and on the REST Framework. Some interesting reference we can look up are the project sites for both Django and Django REST Framework. Reddit has a subreddit dedicated to Django, and of course, nothing beats Stack Overflow if something is not working and we cannot find out why after searching Google and the documentation.

Return to blog