Autenticación por token

  • Por
Qué es la autenticación por token, procedimiento habitual para loguear a los usuarios en APIs REST y recordarles para los futuros accesos al servicio web.

En este artículo vamos a abordar, de manera conceptual, una práctica recurrente a la hora de mantener la seguridad de un API REST, como es la autenticación por token. Como decimos, es habitual en arquitecturas REST, aunque también puede ser usado para cualquier otra, por ejemplo GraphQL u otros mecanismos para implementar servicios web.

La autenticación por token es algo que se tiene que hacer del lado del servidor y por tanto su implementación depende en gran medida de las tecnologías que estemos usando en el backend. Sin embargo, siempre se trabaja con el mismo flujo de aplicación y los conceptos que vamos a describir a continuación son perfectamente válidos para cualquier lenguaje, base de datos o tipo de servidor que podamos estar usando.

Qué es la autenticación por token

Para el que no tenga nociones explicaremos, de manera general, cómo sería un modelo de autenticación adecuado para las APIs.

Si hay algo característico de las API, REST o cualquier otra arquitectura, es que no manejan estado y por lo tanto no tienen sesiones. En el artículo de Qué es REST ya tuvimos ocasión de dar más detalles sobre esto, de modo que no vamos a repetirnos. Lo destacable ahora es que, como consecuencia de no tener estado y no tener sesiones en el servidor para cada usuario, el backend es incapaz de recordar al usuario entre llamada y llamada al API.

Para evitar que en cada llamada el usuario deba entregar su clave y password se usa un token, que no es más que una cadena de texto bien larga, encriptada con una clave. Según se hace el login, el servidor devuelve al cliente un token y el cliente en futuros accesos entrega ese token para certificar que está autenticado.

Nota: Desarrollar basado en API tiene diversas ventajas, como aportar la posibilidad que otros trabajen con tus servicios web desde sus aplicaciones. Pero aunque solo fueses tú quien va a usar un API y no la liberes públicamente, existen diversas ventajas también. Si quieres agregar algo de más información puedes leer también el artículo Un mismo backend, diferentes frontales.

Flujo de autenticación y autorización

En resumen, el flujo de trabajo para la autenticación por token, en el marco del desarrollo frontend, se puede apreciar en la siguiente imagen:

A.- El cliente envía los datos de login

A través de un formulario en la página se recaba el usuario y la clave de acceso. Estos datos se enviarán al servidor. En este punto pueden pasar dos cosas:

  1. Si el login es correcto, se da al cliente por autenticado. Entonces se genera un token en el lado del servidor, que se enviará al cliente de vuelta.
  2. Si el login no fue correcto, entonces se le manda un código de error al cliente.

B.- Almacenar el token

En el caso que se realizase un intento correcto de autenticación, y por tanto el servidor nos devolviese el token, en el lado del cliente se deberá almacenar el token, para poder usarlo más tarde.

Lo ideal será almacenar el token en el navegador, en un lugar donde se pueda acceder a él en futuras consultas. Es decir, sería interesante proveer algún sistema de persistencia, para que por ejemplo, si el usuario refresca la página o accede a la misma web pasados unos minutos, se disponga del token generado anteriormente y no se tenga que obligar al usuario a pasar de nuevo por el proceso de login. Lo más normal para almacenar el token sería el LocalStorage del navegador.

C.- Envío del token en posteriores accesos

Cada vez que el cliente, una vez autenticado, desee acceder de nuevo a un recurso de ese API, entonces tendrá que enviar el token al servidor para informarle que es él mismo y que ya se autenticó correctamente en un paso anterior.

Al recibir el token, el servidor lo tendrá que verificar y, si lo encuentra válido, sabrá que corresponde a un usuario de su aplicación, por lo que podrá conceder el acceso al recurso consultado.

Otras situaciones importantes del flujo de control de usuario

Además del proceso de autenticación de usuarios y posterior autorización en los accesos al API, existen un par de casos adicionales que debemos implementar para el flujo del control de usuario en la aplicación.

Al iniciarse la aplicación

Al arrancar todo el proceso de inicio de la aplicación, sea cual sea el framework Javascript que se esté usando, puede ocurrir que se disponga de un token ya almacenado en un espacio de persistencia en el navegador.

Por lo tanto, también en el lado del frontend, el cliente deberá comprobar si tiene el token en el almacenamiento local.

  1. Si lo tiene, debe verificar que es correcto. Para ello lanzará una request contra el servidor, que es quien puede verificar ese token.
    a) Si es correcto entonces está autenticado. Con lo que el cliente debería modificar el estado de la aplicación para mostrar que el usuario está logueado.
    b) Si no es correcto, entonces se entiende que el token no es válido y por tanto lo lógico será borrarlo del almacenamiento local y mantener el estado de aplicación, mostrando que no está autenticado.
  2. b) Si el cliente no tiene el token en un espacio de almacenamiento, entonces se entiende que no está autenticado y no necesitamos verificar nada. En este caso el estado de la aplicación debería demostrar que no se está logueado.

Al hacer logout

La operativa para hacer logout consiste en borrar el token del almacenamiento local del navegador. Además en la aplicación se debería modificar el estado para indicar al usuario que no se está logueado.

Caducidad del token y refresh token

Otra cosa que no hemos mencionado en este flujo se deriva de la caducidad del token. El token generalmente tiene un tiempo de validez,, que se establece en el servidor, al momento de generar el token.

Durante el tiempo de validez del token podrá ser utilizado para autorizar el acceso a ciertos recursos por parte del cliente autenticado. Sin embargo, si el token ha caducado, entonces el servidor lo rechazará y el cliente no podrá acceder a aquella información u operación solicitada.

Para establecer un flujo mediante el cual se mitiguen posibles problemas por caducidad del token, se puede proporcionar también un token de refresco. Ese token servirá para aumentar el tiempo de validez del token o generar uno nuevo más adelante, sin necesidad de obligar al usuario a volver a enviar sus datos de inicio de sesión.

El token de refresco se utiliza opcionalmente, por lo que no todas las implementaciones deben controlarlo necesariamente.

JSON Web Token

Uno de los estándares para producir los token del lado del servidor es JSON Web Token. Básicamente especifica toda una operativa, que se debe implementar del lado del servidor, para producir tales token y verificar su validez cuando sea necesario.

El estándar JSON Web Token indica que los token del lado del servidor se crean mediante una cadena de texto encriptada por una clave, que se mantiene en secreto del lado del servidor. Esa misma clave se debe de usar para desencriptar el token y verificar su validez.

El token en sí, una vez desencriptado, permite conocer cosas sobre el usuario que ha realizado la solicitud, es decir, es una manera de mantener los datos de sesión y saber cosas del usuario, como su email, nombre o cualquier otra información que la aplicación juzgue necesaria.

Nota: La sesión, que es una parte fundamental de las aplicaciones del lado del servidor, es problemática para su almacenamiento en sistemas distribuidos (por ejemplo en servicios que funcionan mediante balanceo de carga). Por ese motivo, en JSON Web Token se espera que la sesión se almacene en el cliente, como se describió anteriormente. Para aclarar posibles dudas para aquellos que vienen de la programación backend tradicional, en este modelo de autenticación por token también se dispone de unos datos de sesión, solo que la sesión en este caso se almacena en el cliente y no en el servidor. El cliente es el que le manda los datos de sesión al servidor en cada acceso que necesite autorización.

Librerías para JSON Web Token

Dependiendo de la tecnología de backend que se pretenda usar podemos encontrar diferentes librerías para implementar de una manera cómoda la generación y verificación de tokens. Existen librerías para todos los lenguajes de backend y habitualmente los frameworks ofrecen alguna alternativa.

En el caso concreto de Javascript (relevante por ser NodeJS una plataforma habitual para la implementación de APIs REST), la creación y verificación del token se puede hacer con la librería "jsonwebtoken", que es bastante sencilla de utilizar.

Implementación de un proceso de autenticación y autorización por JSON Web Token

En este artículo lo que nos interesaba era dejar claros una serie de conceptos, ya que de por sí este proceso de autenticación y autorización no es trivial. Pero seguro que te interesa contar con alguna idea extra que te permita implementar este esquema habitual de funcionamiento de las aplicaciones modernas.

El proceso tiene dos partes fundamentales para su implementación, que son totalmente independientes entre sí, ya que se deben encarar como dos desarrollos distintos, la parte del cliente y la parte del servidor.

JWT del lado del servidor

Como hemos dicho, la implementación depende mayoritariamente de las tecnologías que usemos del lado del servidor, por lo que sería complicado verlas todas, no obstante, si quieres algo de código puedes echar un vistazo a este artículo, donde se explica un software genérico para creación de un API REST a partir de un JSON, con autorización por JWT.

Otras implementaciones, explicadas paso a paso y con mucho detalle las las vas a encontrar en cursos de EscuelaIT. Te recomiendo el Curso de API RESTful con Laravel o el curso de Desarrollo con NodeJS y MongoDB.

Implementación del lado del cliente de la autenticación y autorización en un API

Para implementar el proceso de autenticación del lado del cliente te recomendamos usar un framework Javascript. Puedes aprender aquí mismo con el Manual de Angular o el Manual de Polymer 2, por ejemplo.

Estos dos frameworks/librerías se explican también en cursos de EscuelaIT donde se ve paso a paso el proceso del cliente para autenticación y autorización. Por ejemplo te recomendamos el curso de Angular (este es el más reciente en el momento de escribir este texto). o el Curso de Desarrollo de aplicaciones con Polymer 2.