Autenticación basada en tokens y cómo aplicarla en tu web

Alanis Simoes
3 min readApr 9, 2021

Desde que empecé a estudiar informática, más de una vez he oído hablar de los tokens, pero nunca llegué a comprender del todo su funcionamiento o qué eran. Ahora que me he visto obligada a usarlos, no me ha quedado más que otra que buscar información sobre estos, ya era hora...

Lo más básico e importante: ¿qué son? Dicho rápido, un token es un código que el usuario envía al servidor para decirle “hey, soy yo”. Esto nos sirve para conocer qué roles tiene este usuario que accede a nuestra web, así sabremos cuáles páginas le podemos mostrar y cuáles ocultar. También es una alternativa al guardado de sesiones, haciendo que sea todo más ligero.

Actualmente, el estándar mas utilizado es el JWT (json web tokens); lucen de esta forma:

Ejemplo de token y su decodificación

Como se puede ver, está dividido en tres partes codificadas, separadas por puntos:

  1. La cabecera, formada por el tipo y el algoritmo utilizado para generar el token
  2. Los datos que queremos enviar para verificar al usuario (payload), suelen ser sus roles y su identificador (en este caso es un correo electrónico)
  3. La firma de verificación, es la parte que verifica que todo corresponda a un token válido.

En mi caso particular, estoy utilizando Symfony para hacer la API de mi proyecto. Para poder implementar la autenticación con JWT hemos decidido utilizar el bundle LexikJWTAuthenticationBundle, pues es bastante sencillo. Como pre-requisitos para poder utilizarlo es necesario tener una versión de Symfony superior a la 3.4, la extensión de OpenSSL y el security bundle de Symfony.

Los pasos a seguir aparecen aquí, pero yo explicaré rápidamente cómo hacerlo con Symfony 5:

Primero, agregamos el bundle a nuestro proyecto con php bin/console require "lexik/jwt-authentication-bundle" . Después generamos las SSL keys con el comando php bin/console lexik:jwt:generate-keypair .

Ahora tendremos en el archivo .env lo siguiente:

###> lexik/jwt-authentication-bundle ###JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pemJWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pemJWT_PASSPHRASE= -clave secreta-###< lexik/jwt-authentication-bundle ###

Como se indica, las claves estarán guardadas en la ruta config/jwt .

Por último nos queda configurar el archivo security.yaml y añadir una ruta para la comprobación.

####config/packages/security.yaml####
firewalls:
login:
pattern: ^/api/login
stateless: true
anonymous: true
json_login:
check_path: /api/login_check
success_handler:
lexik_jwt_authentication.handler.authentication_success
failure_handler:
lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }

Ahora tenemos puesto que nuestra ruta de login es visible para cualquiera (anonymous: true) y que todas las rutas que comiencen con /api , para poder acceder a ellas, será necesario validarse con el token generado. La ruta donde se comprobarán los datos y se generará el token es /api/login_check . Para poder hacer uso de ella, es necesario declararla. Por esto vamos al archivo routes.yaml y añadimos:

####config/routes.yaml####
api_login_check:
path: /api/login_check

Por parte del servidor, ¡ya tendríamos todo! Para poder acceder desde el lado cliente, recibimos el token al hacer login y con cada request, lo enviamos en el header como authorization: Bearer {token} ; si tenemos permisos, podremos acceder. 🥳

--

--