Token de autenticación en la Rest Api emplando Django Rest Framework

- Andrés Cruz

In english
Token de autenticación en la Rest Api emplando Django Rest Framework

Proteger una Rest Api como la construida anteriormente ya sea de tipo CRUD o cualquier otra, para que solo puedan ser accedido mediante algún mecanismo es una característica común hoy en día y un mecanismo muy empleado es mediante Tokens, Tokens de Autenticación y esto en Django Rest Framework lo podemos hacer fácilmente sin mucha complicación.

La autenticación vía Tokens es un esquema ampliamente en las aplicaciones web en la cual definimos nuestra Rest Api, para proteger ciertos recurso o inclusive toda la Rest Api; todo esto nosotros lo podemos configurar fácilmente en una Rest Api creada con Django Rest Framework cosa que vamos a hacer en esta entrada.

Puntos a tener en cuenta

Para crear nuestra Rest Api con protección de tokens de autenticación lo podemos hacer nativamente empleando Django Rest Framework, para esto, tenemos que definir un par de configuraciones en nuestro archivo de settings, específicamente en la key o clave de REST_FRAMEWORK que es la que empleamos para manejar este tipo de configuraciones a todo nivel.

Proteger una Rest Api

La configuración que vamos a hacer sería para aplicar globalmente en una clase de tipo Rest; ya que como puedes ver, al momento de trabajar con DRF tenemos muchas maneras de hacer lo mismo y aquí simplemente te ofrecemos una versión. Simplemente tienes que indicar en el archivo de configuración de tu proyecto en Django, el llamado settings.py y agregar la siguiente configuración:

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

Luego, tenemos que agregar la siguiente configuración en en nuestra clase (EN caso de que la quieras hacer local a una clase, puedes evitar la configuración de 'DEFAULT_PERMISSION_CLASSES'); una de las propiedades que cualquier clase tipo Rest viene siendo la siguiente:

permission_classes = [IsAuthenticated]

Y con el valor anterior le estamos indicando que el usuario tiene que estar autenticado;  con que backend o clase de autenticación te pudieras preguntar, con el indicado en el archivo settings.py de nuestro proyecto.

Es necesario estar autenticado DEFAULT_PERMISSION_CLASSES y la siguiente es que vamos a emplear como backend, el sistema de tokens; ahora, también tenemos que indicar que vamos a emplear la aplicación de tokens:

'rest_framework.authtoken',

Y listo, ya con esto protegemos nuestra RestApi en Django con Tokens de autenticación.

Ya con las configuraciones que realizamos anteriormente, podemos ejecutar las migraciones para la aplicación que creamos anteriormente; puedes indicar las migraciones de la aplicación que definimos anteriormente:

python manage.py migrate authtoken

Esto es útil si nosotros NO estamos empleando el sistema de migraciones de Django, en casos -por ejemplo- de que estemos empleando MongoDB con Django, que al menos para manejar las tablas/colecciones creadas por nosotros, no debería ser necesario aplicar las migraciones.

O si empleas el esquema tradicional y tienes tus migraciones al dia:

python manage.py migrate 

Crear la función para generar los Tokens de autenticación y verificar credenciales (login)

Ahora, lo siguiente que tenemos que hacer sería crear la función que emplearía nuestro usuario para generar el token, este método o función será un recurso Rest personalizado por nosotros que nos permitirá generar dicho token mediante la función de  get_or_create del modelo Token que importamos de gratis de nuestro DRF.

Ahora, generamos dicho token una vez comprobadas las credenciales del usuario con la que tenemos en el modelo de User y en la base de datos; así que, finalmente:

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)

Explicación de la función anterior

Como puedes ver, al ser este el recurso que tenemos que emplear para el login, y al tener toda la Rest Api protegida mediante los tokens auth, tenemos que indicar específicamente que el recurso anterior puede ser accedido sin necesidad de que este token esté presente en la petición que estamos enviando; por lo tanto, empleamos el decorador de permission_classes con el valor de AllowAny para que sea de acceso público; por lo demás, es una sencilla comprobación de credenciales como la que hicimos anteriormente para comprobar las credenciales; por lo demás, tenemos la generación del token de autenticación al cual le tenemos que pasar el usuario al cual le queremos crear o buscar en caso de que exista, el token.

La función realmente se auto explica sola, tenemos los parámetros que recibimos vía una petición post, en este caso empleamos los mismos usuarios que emplea Django de manera interna en toda la aplicación. Por lo tanto el proceso de login personalizado emplea la función de check_password que nos provee Django para tal fin; ahora, desde Postman podemos consumir la función anterior:

Login a Postman en Django

Y si el login va bien, creamos (en caso de que no exista) y devolvemos el token de autenticación que tiene que emplear nuestro usuario para realizar peticiones.

Luego creamos la ruta para esta función:

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

Y ahora, cuando queramos realizar una petición, tenemos que enviar el token; por ejemplo, empleando 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.