Candado con llave

Symfony, Autenticación JSON Web Token

Hoy os voy a contar que es la autenticación JSON Web Token o JWT y veremos un ejemplo de implementación utilizando Symfony.

¿Que es la autenticación basada en token?

La autenticación tradicional, se gestiona mediante sesiones. El usuario se loguea con sus credenciales, el servidor las valida y guarda en una sesión la información del usuario.

La autenticación basada en tokens es stateless. Esto quiere decir que no guarda ningún tipo de información del usuario en el servidor ni en la sesión.

El funcionamiento es el siguiente, un usuario se autentica contra la API, por ejemplo mediante el envío de un usuario y una contraseña. El servidor valida las credenciales y si son correctas, envía al usuario un Token encriptado. El usuario almacena el Token y a partir de entonces, cada petición HTTP que haga el usuario, va acompañada del Token en la cabecera. Este Token no es más que una firma cifrada que permite a nuestra API identificar al usuario.

De esta forma, no se guarda ningún estado entre las diferentes peticiones contra la API por lo que la autenticación se puede realizar desde diferentes tipos de clientes.

¿Que es JSON Web Tokens o JWT?

JWT es es un estándar abierto (RFC 7519) que nos permite la transmisión de datos de forma segura. Los token pueden ser firmados mediante clave simétrica (algoritmo HMAC) o mediante clave asimétrica (RSA). JWT contiene toda la información que necesitemos sobre el usuario, de forma que se evita la necesidad de repetir consultas a base de datos para obtener estos datos.

Un token con JWT tiene el siguiente formato:

El formato de un JWT está compuesto por 3 strings separados por un punto .

Header: Cabecera del Token, compuesta por dos partes, el tipo y el algoritmo de encriptación.

Payload: Contiene los datos que definen nuestro Token. Estos valores pueden ser propios de la especificación de JWT o pueden ser valores personalizados.

Signature: El último valor del Token es la firma, y es un string generado mediante la codificación del header y el payload con una clave secreta almacenada en el backend.
Una herramienta muy útil para probar como se genera un token JWT es jwt.io

Si introducimos el siguiente token, en el apartado Debugger de esta herramienta:

Podemos ver que los valores de cada parte del token coinciden con los de los ejemplos anteriores. Además en esta web podéis encontrar librerías para un montón de lenguajes de programación.

Bueno y después del rollo que os hemos contado, si todavía os quedan ganas, vamos a ver cómo implementar la autenticación con JWT con Symfony.

En Symfony tenemos un bundle que nos resuelve gran parte del problema, se trata de LexikJWTAuthenticationBundle

Instalamos el bundle:

Lo registramos en app/AppKernel.php:

Necesitamos crear las claves con la que se firmará el token, para ello creamos una carpeta y generamos una clave privada y una clave pública:

Configuramos el bundle en el fichero app/config/config.yml, indicando las rutas de las claves, la pass y la caducidad.

Ya tenemos en bundle configurado!!

Ahora vamos a ver un ejemplo de implementación de una acción que se encargue de hacer login y generar un Token JWT usando el bundle.

Con la acción anterior cualquier cliente podría solicitar un Token a nuestra API, llamando por ejemplo a la url: https://api.com/javiernuber@gmail.com/1234

Una vez que el cliente ha obtenido el Token, tendrá que enviarlo en las cabecera de las sucesivas peticiones para poder autenticarse.

¿Como autenticamos con un JSON Web Token?

Gracias al componente Guard de Symfony podemos implementar nuestro propio sistema de autenticación. Básicamente, lo que haremos es que en cada petición, intentaremos encontrar al usuario del token JWT que nos llega en la cabecera, si lo encontramos, autenticamos al usuario y si no, rechazamos la petición.

Para crear un sistema de autenticación, simplemente creamos una clase y hacemos que implemente GuardAuthenticatorInterface o extendemos a AbstractGuardAuthenticator.
Para ello implementamos la clase JWTAuthenticator y la registramos como servicio.

Por último definimos un nuevo firewall que se encargue de proteger las urls de la API en el que usamos el authenticator que hemos definido.

Como veis las posibilidades que ofrece el componente de seguridad de Symfony son espectaculares y esto no es todo, en próximos post veremos como resolver más problemas típicos en nuestras aplicaciones, mientras tanto os animo a revisar la documentación de este fantástico componente

Espero que esta guía os sirva de ayuda, nos vemos pronto 🙂