Security
Back End
APIs
Hay varias formas de crear una capa de autenticación en las aplicaciones web, pero hoy nos vamos a centrar en la Autenticación Basada en Token o Token Based Authentication por varias razones:
Autenticación significa ser capaz de identificar quién está haciendo peticiones a tu API, normalmente implementas una capa de autenticación en tu aplicación porque quieres:
Para explicar en detalle la "Autenticación de una API basada en tokens" es mejor empezar explicando lo que son los tokens.
A grandes rasgos, un token es un "número que prueba algo", por ejemplo: Cuando terminas de hacer una transferencia bancaria, el banco envía un "token" de confirmación que sirve como prueba para validar que la transacción existe y es válida. Ese número de confirmación podría llamarse también token de confirmación.
Otros ejemplos cotidianos de tokens:
Los tokens utilizados para la autenticación tienen que ser algo más que números normales, tienen que ser casi imposibles de falsificar, predecir o decodificar.
Hay varios tipos de tokens que puedes usar para tu sistema de autenticación como Basic, Bearer, o JWT. La mayoría de ellos utilizan algoritmos de criptografía avanzada que no vamos a tratar en esta lección (puedes ver este increíble vídeo para aprender más). En su lugar, vamos a hablar de hash.
Un hash es un número alfanumérico único que se genera a partir de una semilla o valor específico, por ejemplo:
Con Python
1import hash_function 2 3value = "alex" 4unique_hash = hash_function(value)
Explicación: la función hash_function
siempre devolverá exactamente el mismo unique_hash
si se da el mismo valor, echa un vistazo a esta demostración, empieza a escribir en la entrada:
Con JavaScript
1const jwt = require('jsonwebtoken'); 2 3const payload = { 4 userEmail: 'hola@4geeks.co', 5 rol: 'admin' 6}; 7 8const unique_hash = jwt.sign(payload, 'secret-key', { 9 expiresIn: '24h' // Establece el tiempo de expiración a 24 horas 10});
Explicación: la función jwt.sign
siempre devolverá el mismo unique_hash
si se proporciona el mismo valor. Echa un vistazo a esta demostración, empieza a escribir en la entrada:
Nota: Hay varias funciones de hashing populares: MD5, Sha1, Sha256, Sha256, etc.
Las funciones hashing se han convertido en la mejor forma de generar tokens en el mundo de la seguridad porque
Nota: Cada dirección de billetera bitcoin tiene un hash único, cada commit que haces en GitHub tiene un hash único, etc.
La forma más sencilla de implementar la autenticación en tu base de datos y en tu API:
User
que represente a cada usuario dentro de tu aplicación.POST /token
que genere un token solo si recibe un email y una contraseña que se encuentren en la base de datos.POST /token
devolverá el token al front-end si todo está bien.En el momento en que generas el token puedes decidir si quieres que caduque, de la misma manera que las sesiones web caducan cuando te conectas a tu cuenta bancaria online.
Cuando un cliente se autentique con éxito recibirá ese token único y podrá adjuntarlo a los headers de las peticiones que realice a partir de ese momento, ese token será la "sesión del usuario".
Se recomienda guardar ese token en las cookies o localStorage
de tu aplicación front-end.
1let myToken = "aDSA45F$%!sd&sdfSDFSDFytrefERF"; 2localStorage.setItem("token", myToken); 3 4// Puedes recuperar el token en cualquier momento, en cualquier lugar de tu aplicación utilizando: 5let myToken = localStorage.getItem("token");
Si estás haciendo una petición desde el front-end esta será una forma ideal de adjuntar el token a tus Authorization headers:
1let myToken = localStorage.getItem("token"); 2fetch('https://myApi.com/path/to/endpoint', { 3 method: "POST", // o cualquier otro método 4 headers: { 5 "Authorization": myToken, // ⬅⬅⬅ authorization header 6 }, 7 body: JSON.stringify(body) 8}) 9 .then(resp => resp.json()) 10 .then(data => console.log("Success!!", data)) 11 .catch(error => console.log(error));
Hay muchas formas de crear tokens: Basic, Bearer, JWT, etc. Todas ellas son diferentes en su naturaleza, pero el resultado es la misma salida: Un hash (un gran token alfanumérico).
Tipo de token | Ejemplo |
---|---|
Token Básico | ecff2099b95ed507a27a4717ec78965d529cc346 |
Token Bearer | YWxlc2FuY2hlenI6NzE0YmZhNDNlN2MzMTJiZTk5OWQwYWZlYTg5MTQ4ZTc= |
Token JWT | eyJhbGciOiJIUzI1NiIsInR5c.eyJzdWIiOFt2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpM |
☝️ Como puedes ver, los Tokens JWT son más grandes que los otros dos tipos de token.
JSON Web Token o JWT es un estándar abierto para crear tokens
Este estándar se ha vuelto bastante popular, ya que es muy efectivo tanto para las Web Apps como las APIs de Google, donde después de la autenticación del usuario se hacen peticiones a la API.
El Token Web JSON es un tipo de token que incluye una estructura, que puede ser descifrada por el servidor, que permite autenticar la identidad del usuario de esa aplicación.
En pocas palabras: JWT es una alternativa increíble porque el Token básico o Basic Token
es demasiado simple y fácil de hackear y el Token Bearer es más difícil de mantener porque tienes que almacenar cada token en la base de datos.
Con los tokens JWT no necesitas una base de datos, el propio token contiene toda la información necesaria.
Puedes observar que el string o cadena está dividida en tres secciones separadas por un punto .
- cada sección tiene su significado:
Section name | |
---|---|
HEADER | La primera parte almacena el tipo de token y el algoritmo de encriptación. |
PAYLOAD | La segunda parte tiene los datos que identifican al usuario: puede ser su ID, nombre de usuario, etc. |
SIGNATURE | Firma digital, que se genera con las dos secciones anteriores, y permite verificar si el contenido ha sido modificado. |
Puedes dividir un proceso de autenticación estándar en 5 pasos principales:
User
que coincida con ambos parámetros al mismo tiempo (nombre de usuario y contraseña).token
para ese usuario y responde status_code=200
al front-end.token
a partir de ahora para realizar cualquier solicitud futura.Recomiendo encarecidamente el uso de Flask JWT Extended.
Genera tokens con JSONWebToken en Node. Además, utiliza Express JWT para hacer cumplir los endpoints privados en Express.