Authentication token in Rest API using Django Rest Framework

- Andrés Cruz

En español
Authentication token in Rest API using Django Rest Framework

Protecting a Rest Api like the one built above, whether CRUD type or any other, so that they can only be accessed through some mechanism is a common feature today and a widely used mechanism is through Tokens, Authentication Tokens and this in Django Rest Framework we can do it easily without much complication.

Authentication via Tokens is a scheme widely used in web applications in which we define our Rest API, to protect certain resources or even the entire Rest API; we can easily configure all this in a Rest Api created with Django Rest Framework, which we are going to do in this post.

Points to consider

To create our Rest Api with authentication token protection, we can do it natively using the Django Rest Framework, for this, we have to define a couple of configurations in our settings file, specifically in the REST_FRAMEWORK key or key, which is what we use to handle this type of configuration at all levels.

Protect a Rest API

The configuration that we are going to do would be to apply globally in a class of type Rest; since as you can see, when working with DRF we have many ways to do the same and here we simply offer you a version. You simply have to indicate in the configuration file of your project in Django, the call settings.py and add the following configuration:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES':[
        'rest_framework.permissions.IsAuthenticated'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES':[
        'rest_framework.authentication.TokenAuthentication'
    ]
}

Then, we need to add the following setting to our class (IN case you want to make it local to a class, you can skip the 'DEFAULT_PERMISSION_CLASSES' setting); one of the properties that any Rest-type class has been the following:

permission_classes = [IsAuthenticated]

And with the previous value we are indicating that the user has to be authenticated; With which backend or authentication class could you ask, with the one indicated in the settings.py file of our project.

It is necessary to be authenticated DEFAULT_PERMISSION_CLASSES and the following is that we are going to use the token system as a backend; now, we also have to indicate that we are going to use the token application:

'rest_framework.authtoken',

And that's it, with this we protect our RestApi in Django with authentication tokens.

Already with the configurations that we made previously, we can execute the migrations for the application that we created previously; you can indicate the application migrations that we defined above:

python manage.py migrate authtoken

This is useful if we are NOT using Django's migration system, in cases -for example- that we are using MongoDB with Django, that at least to handle the tables/collections created by us, it should not be necessary to apply migrations.

Or if you use the traditional scheme and have your migrations up to date:

python manage.py migrate 

Create the function to generate the authentication tokens and verify credentials (login)

Now, the next thing we have to do is create the function that our user would use to generate the token, this method or function will be a custom Rest resource that will allow us to generate said token using the get_or_create function of the Token model that we import for free. of our DRF.

Now, we generate said token once the user's credentials have been verified with the one we have in the User model and in the database; so finally:

from rest_framework.decorators import api_view
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
 
from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
 
@api_view(['POST'])
def login(request):
 
    username = request.POST.get('username')
    password = request.POST.get('password')
 
    try: 
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        return Response("Usuario inválido")
 
    pwd_valid = check_password(password,user.password)
 
    if not pwd_valid:
        return Response("Contraseña inválida")
 
    token, _ = Token.objects.get_or_create(user=user)
 
    return Response(token.key)

Explanation of the above function

As you can see, since this is the resource that we have to use for the login, and since we have all the Rest APIs protected by means of auth tokens, we have to specifically indicate that the previous resource can be accessed without the need for this token to be present in the request we are sending; therefore, we use the permission_classes decorator with the value of AllowAny to make it publicly accessible; otherwise it's a simple credential check like we did earlier to check credentials; for the rest, we have the generation of the authentication token to which we have to pass the user to whom we want to create or search, if it exists, the token.

The function is really self-explanatory, we have the parameters that we receive via a post request, in this case we use the same users that Django uses internally throughout the application. Therefore, the custom login process uses the check_password function provided by Django for this purpose; now, from Postman we can consume the previous function:

Login a Postman en Django

And if the login goes well, we create (if it doesn't exist) and return the authentication token that our user has to use to make requests.

Then we create the route for this function:

urlpatterns = route.urls
urlpatterns += path('login',views.login),

And now, when we want to make a request, we have to send the token; for example, using Postman:

Prueba consumir recurso con token en postman
Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.