En este artículo comenzaremos a explorar el tema de la autenticación en Django desde Vue.JS. Dedicaré dos artículos a ello. El primero será éste y se centrará más bien en el backend de Django-Rest-Framework.
JWT: ¿Qué es?
JWT es un acrónimo que procede de “JSON Web Token”. JWT consiste en emitir desde nuestro servidor un token de corta duración para que los clientes se autentiquen a sí mismos sin tener que mantener una sesión activa.
¿Por qué tenemos que usar JWT?
Porque éste es el mecanismo más seguro que se suele utilizar para autenticarse en una API. A primera vista se nos podría ocurrir el método fácil de generar una clave que no caduque y sólo conocen cliente y servidor con el fin de que puedan autenticarse. Pero este token representaría un importante problema de seguridad en el momento en el que queda expuesto a un usuario no autorizado (que puede acceder a ella mediante un ataque man-in-the-middle).
A diferencia de utilizar una simple clave de API, JWT introduce un nivel de seguridad adicional añadiendo una marca de tiempo y un tiempo de caducidad al token. De ésta manera, cuando el token expira debe ser renovado. Así, un tercero podría llegar a acceder a un token pero no durante mucho tiempo, ya que éste caducaría rápidamente.
¿Por qué no usamos sesiones basadas en cookies como en la típica aplicación monolítica en Django?
Si creamos dos capas desacopladas, seguramente estamos planteando esta arquitectura para garantizar la escalabilidad horizontal de nuestra aplicación. Dicha escalabilidad sería muy compleja manteniendo información de sesión con cookies. Así que debemos eliminar el estado de nuestra aplicación si queremos que ésta sea más escalable.
Utilizar un sistema JWT, nos va a proporcionar un valioso mecanismo para dos escenarios concretos:
Autorización: este es el escenario más común para usar JWT, ya te lo he comentado antes. Una vez que el usuario haya iniciado sesión obtiene un token con fecha de caducidad, y a partir de entonces cada solicitud posterior incluirá el JWT. Dicho token le permitirá acceder a las rutas, servicios y recursos permitidos por nuestro backend Django.
La mejor forma de implementar esto hoy por hoy es el mecanismo de Single Sign On, ya que implica muy poca sobrecarga para nuestro servidor y permite compartir un mismo backend entre varios dominios. Esto nos permitiría por ejemplo, reutilizar nuestro backend para una web, una aplicación móvil y una aplicación de escritorio al mismo tiempo.
Intercambio de información: los tokens web JSON son una buena forma de transmitir información de forma segura entre dos partes de la aplicación. Como los JWT se pueden firmar, por ejemplo, usando pares de claves públicas / privadas, puede estar seguro de que los remitentes son quienes dicen ser (mecanismo de autenticación). Además, como la firma se calcula utilizando el encabezado y la carga útil, también puedes verificar que el contenido no haya sido alterado (mecanismo de integridad).
Implementando todo esto en DJANGO
Vamos a meter las manos en harina. Ahora que has entendido cómo funciona JWT y por qué es interesante implementarlo en tu API-REST (tu backend), veamos cómo se hace ésto con Django.
- Instalar djangorestframework_jwt:
Como siempre, utilizaremos pip para instalarlo:
1 2 | pip install djangorestframework_jwt |
- Añadir algunos parámetros de configuración a nuestro settings.py:
1 2 3 4 5 6 7 | # settings.py JWT_AUTH = { 'JWT_ALLOW_REFRESH': True, 'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1), 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7), } |
- Añadir jwt a nuestro proyecto:
Aquí simplemente tenemos que añadir este mecanismo en las vistas genéricas de nuestro Django-Rest-Framework. En el siguiente ejemplo, por ejemplo, lo Utilizaremos en una clase genérica ListAPIView que nos devuelve la lista de artículos de un blog:
1 2 3 4 5 6 | # views.py ... relevant imports ... class ArticulosView(ListAPIView): authentication_class = (JSONWebTokenAuthentication,) # Añado una coma porque authentication_class debe ser una tupla permission_classes = (IsAuthenticated,) # Añado una coma porque permission_classes debe ser una tupla |
- Ahora tenemos que crear los endpoints JWT necesarios para refrescar y obtener el token en el fichero urls.py:
1 2 3 4 5 6 7 8 9 | # urls.py from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token urlpatterns = [ ... url(r'^auth/obtener_token/', obtain_jwt_token), url(r'^auth/refrescar_token/', refresh_jwt_token), ... ] |
Vamos a probar esto
La forma más sencilla de probar ésto (no entraremos en la forma de crear Test Cases pues no es el objetivo del artículo) es utilizar curl. Tenemos que tener un usuario creado en nuestro sistema, y utilizaremos la siguiente estructura para pasársela a nuestra API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | { "username": "<your_username>", "password": "<your_password>" } ```</your_password></your_username> El comando curl es el siguiente: ```bash curl -X POST -H "Content-Type: application/json" -d '{"username":"<your_username>","password":"<your_password>"}' http://localhost:8000/auth/obtain_token ```</your_password></your_username> Y deberíamos obtener algo parecido a esto: ```json { "token": "gyiuguy78y7987H87HG987h798h987H987H9870HOJ54g645g6436435g64u567i786o8563t3t342g9812ey8dn2r8932154du0193cru81325ruc809ºur80ur3n08ur3m0832ur898" } |
Ahora vamos a probar cómo se refresca el token:
1 2 | curl -X POST -H "Content-Type: application/json" -d '{"token":"gyiuguy78y7987H87HG987h798h987H987H9870HOJ54g645g6436435g64u567i786o8563t3t342g9812ey8dn2r8932154du0193cru81325ruc809ºur80ur3n08ur3m0832ur898"}' http://localhost:8000/auth/refresh_token/ |
Y ahora ya tenemos correctamente configurado un mecanismo JWT de autenticación para nuestra API REST. En el siguiente artículo veremos como consumir estos servicios desde Vue.js
CONTINUARÁ…
Muy bueno espero la segunda parte