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, 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 a 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 DjangoUser
instancerequest.auth
will beNone
If using BasicAuthentication
in production make sure your API is only available over https
and 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 run 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 successfully authenticated, the TokenAuthentication scheme provides the following credentials:
request.user
which is a DjangoUser
instancerequest.auth
which will be arest_framework.authtoken.models.Token
instance
Generating Tokens
To generate tokens we have a few options available to us:
1. Exposing an API endpoint 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 endpoint with a JSON body containing a username and password.
{
"username": "<name of the user>",
"password": "<user password>"
}
The endpoint 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: Authentication
Feel free to respond to this story in case there is anything that is not very clear and also follow me for more content like this.
You can connect with me here:
Ciao 🤓
Mobile app alchemist who is trying to transmute elegant designs, into elegant code, into beautiful mobile app experiences.