Foad Moha

Foad Moha

Backend Python Developer

© 2021

Authentication in Django REST Framework

In this post I will go through some common authentication mechanisms that are used in Django REST Framework (DRF). Some of these methods are included in DRF, and the others are custom authentication packages that implement popular schemes not included in DRF. We will go through how each scheme works and when it should be used. I have also included some resources for learning how to implement each.

Before we dig in, we need to look at how authentication works in DRF.

Authentication in Django REST Framework

Authentication is a way for your service to determine whether the user is who they claim to be. When that is determined, your service can check whether they are allowed to access certain information.

In DRF, authentication is the first check that happens upon receiving a request. All other checks (like permissions, throttling, etc) are done afterwards. You can have several ways of authenticating users for the same API service, each used for a different type of client. You can set your API’s authentication schemes globally in your setting file:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

In this case DRF will first try the BasicAuthentication scheme for each request. If that fails, it will try the next authentication scheme in the list and so on.

You can also override these global settings for each view individually. For example this view will only allow requests that use the TokenAuthentication scheme:

class SomeSpecialView(APIView):
    authentication_classes = [TokenAuthentication]

If you do choose to have specific authentication schemes for specific views make sure you always have a global one set in your settings file to fall back on.

A tour of common authentication schemes

BasicAuthentication

This is the most … uh … basic authentication scheme you can have. Users identify themselves with a username and password. This is also the least secure scheme. Users will be sending their precious passwords over the wire. Only use it in testing. If you absolutely must use it, make sure your API is only available over HTTPS.

You can implement it by just importing it from DRF and adding it to to a specific view or to your settings.py as a default authentication class.

Users then send requests to the API and include HTTP Basic Authentication header:

GET https://example.com/api/books/123/
Authorization: Basic myusername mypasswd

TokenAuthentication

In this scheme you give each user a unique token and they include it in every request they make. This is appropriate for client-serer applications, for example for desktop or mobile apps that need to access your API. Note that anyone that gets hold of the token can use it and authenticate themselves as a user.

To implement TokenAuthentication you need to add rest_framework.authtoken to the list of INSTALLED_APPS in your settings.py file. This app takes care of creation, validation and management of user tokens in your database. Therefore you need to run migrations after you add it so that it can create token management tables in the database. Then you need to a way to create token for each user and give it to them. For example in your web app you can make a page where logged in users can see their token. You create tokens for your users like this:

# views.py
from rest_framework.authtoken.models import Token

@login_required
def user_token_view(request):
    token = Token.objects.create(user=request.user)
    return render(request, 'myapp/user_token.html', {'token': token.key})

You should provide a way for users to generate a new token (and therefore revoke the old one) in case they feel like the token has been compromised.

Your users then can send requests to your API and authenticate themselves by adding the token to the Authorization HTTP header:

GET https://example.com/api/books/123/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

SessionAuthentication

This scheme is particularly good for Single Page Applications where the user logs in to your app, creates a session in Django and then the app sends AJAX requests to the server to fill the page with relevant information. This scheme works based on Django’s session framework so make sure it is included in INSTALLED_APPS in your settings.py files. Read more about Django sessions here.

Django has excellent documentation on how to securely make AJAX calls using Django sessions.

OAuth2

OAuth2 is a popular standard for authentication. It provides guidelines for user authentication as well as authenticating third-party apps on behalf of the user. Here and here you can read more about details of each authentication “flow” and their appropriate use cases.

You can find the technical standard specification here.

Thankfully you don’t need to implement this giant standard yourself. You can use the excellent Django OAuth Toolkit package. They also have a specific section in their documentation for using it with DRF.

JSON Web Token (JWT) Authentication

This is a new and popular standard that works similar to TokenAuthentication except that it does not need to save tokens in the database. Your app generates JWTs that are signed using a secret. Then you give this token to the user to include in their request just as in TokenAuthentication.

Every time you receive the token, you decode it and check its signature. If it’s valid you know that it has not been tampered with. The token is actually nothing but a json string that includes some claims. These claims can be the username, token expiry date, etc. You can read more about the details of the token here.

For JWT authentication you can use the Simple JWT package that implements it for DRF.

A word on Security

I hope this guide has given you a good overview of the most common authentication schemes to use with Django REST Framework. Be aware that no authentication scheme is perfect from the security perspective. Make sure you do extensive research before choosing an authentication scheme and always follow best practices provided by Django and DRF documentations. You are not only responsible for the security of your app, you are also responsible for the security of your users and their data.