Authentication for Django REST APIs

Jordan
3 min readDec 20, 2023
Photo by Faisal on Unsplash

Authentication aims to associate an incoming request with an existing user credential. Permission and throttling policies determine whether a request should be permitted or not.

Authentication always runs at the very start of the view before any other code is allowed to run.

The authentication schemes are always defined as a list of classes, Rest Framework attempts to authenticate with each class in the list and will set request.auth and request.user using the return value of the first class that authenticates successfully.

If no class authenticates the request.user will be set to an instance of django.contrib.auth.models.AnonymousUser and UNAUTHENTICATED_TOKEN settings.

Setting an authentication scheme

The default authentication scheme can be set globally using the DEFAULT_AUTHENTICATION_CLASSES setting.

# global authentication scheme set in settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}

You can also set the authentication classes on per-view basis if you are using the @api_view decorator with function based views.

from rest_framework.response import Response
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import TokenAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated

@api_view(['GET'])
@authentication_classes([TokenAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
def addData(request):
# perform some actions
return Response()

When the authentication fails, it can fail for any of the two reasons below;

  • HTTP 401 Unauthorized
  • HTTP 403 Permission Denied

HTTP 401 errors always include a WWW-Authenticate header that informs a client how to authenticate while a HTTP 403 does not.

The first authentication scheme defined for a view is used to determine the kind of response returned.

Basic Authentication Scheme

This scheme uses HTTP Basic Authentication signed against a user’s username and password and it is only appropriate for testing.

If it successfully authenticates, it provides the following credentials

- request.user which is a Django user instance

- request.auth will be None

If using BasicAuthentication in production make sure your api is only available over https

And also ensure that the clients request for the username and password at login and never store them to persistent storage.

Token Authentication Scheme

This scheme uses a simple token based HTTP authentication scheme and I would recommend it because it requires a token to authenticate a request. Firstly we need to add TokenAuthentication to the list of authentication schemes and then add rest_framework.authtoken to the list of installed apps

INSTALLED_APPS = [
...
'rest_framework.authtoken'
]

Make sure to manage.py migrate after updating the settings.

For clients to authenticate we shall need to include an authentication header like this.

Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

If successful authenticated the TokenAuthentication scheme provides the following credentials

- request.user which is a Django User instance

- request.auth which will be a rest_framework.authtoken.models.Token instance

Generating Tokens

To generate tokens we have a few options available to us

1. Exposing an API end point to generate tokens

Rest framework provides a built in way to generate tokens. We need to add the obtain_auth_token view to our URL config.

from rest_framework.authtoken import views

urlpatterns = [
'''
path('api-token-auth/', views.obtain_auth_token)
]

We can make a post request to this end point with a JSON body containing a username and password.

{ 
"username": "<name of the user>",
"password": "<user password>"
}

The end point will return a result that contains a token that we can use to authenticate requests for that user.

{ "token" : "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" }

2. Using django manage.py to generate tokens

Using the CLI we can run this command to create a token for a user

./ manage.py drf_create_token <username>

This will return the API token for the user, creating it if it does not exist

Generated token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b for user user1

To regenerate a token for a user after it has been compromised, we can use this command

./manage.py drf_create_token -r <username>

To learn more about Django Rest framework authentication here is the official documentation.

Feel free to respond to this story incase there is anything that is not very clear and also follow me for more content like this.

You can connect with me here;

/linkedin

/twitter

Ciao 🤓

--

--

Jordan

Mobile App Alchemist who is trying to transmute elegant designs, into elegant code, into beautiful mobile app experiences.