Cómo JSON Web Token (JWT) protege su API

Probablemente haya escuchado que JSON Web Token (JWT) es la tecnología de vanguardia actual para proteger las API.

Como la mayoría de los temas de seguridad, es importante comprender cómo funciona (al menos un poco) si planea usarlo. El problema es que la mayoría de las explicaciones de JWT son técnicas y provocan dolores de cabeza.

¡Veamos si puedo explicar cómo JWT puede asegurar su API sin cruzar los ojos!

Autenticación de API

Ciertos recursos de API necesitan acceso restringido. No queremos que un usuario pueda cambiar la contraseña de otro usuario, por ejemplo.

Es por eso que protegemos ciertos recursos para que los usuarios proporcionen su identificación y contraseña antes de permitir el acceso; en otras palabras, los autenticamos.

La dificultad de asegurar una API HTTP es que las solicitudes son apátrida – la API no tiene forma de saber si dos solicitudes fueron del mismo usuario o no.

Entonces, ¿por qué no exigimos a los usuarios que proporcionen su ID y contraseña en cada llamada a la API? Solo porque sería una experiencia de usuario terrible.

Token web JSON

Lo que necesitamos es una forma de permitir que un usuario proporcione sus credenciales solo una vez, pero luego el servidor lo identifique de otra manera en solicitudes posteriores.

Se han diseñado varios sistemas para hacer esto, y el estándar actual de última generación es JSON Web Token.

Hay una excelente articulo sobre el tema lo que hace una buena analogía sobre cómo funcionan los tokens web JSON:

En lugar de una API, imagine que se está registrando en un hotel. El “token” es la tarjeta plástica de seguridad del hotel que recibe y que le permite acceder a su habitación y a las instalaciones del hotel, pero no a la habitación de nadie más.

Cuando sales del hotel, devuelves la tarjeta. Esto es análogo a cerrar sesión.

Estructura de la ficha

Normalmente, un token web JSON se envía a través del encabezado de las solicitudes HTTP. Así es como se ve uno:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

De hecho, el token es la parte posterior a “Autorización: Portador”, que es solo la información del encabezado HTTP.

Antes de concluir que es un galimatías incomprensible, hay algunas cosas que puede notar fácilmente.

En primer lugar, el token consta de tres cadenas diferentes, separadas por un punto. Estas tres cuerdas son codificado en base 64 y corresponden a la encabezamientola carga útily el firma.

// Header
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
// Payload
eyJzdWIiOiIxMjM0NTY3ODkwIn0
// Signature
dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

Nota: la base 64 es una forma de transformar cadenas para asegurarse de que no se arruinen durante el transporte a través de la red. No es un tipo de encriptación y cualquiera puede decodificarlo facilmente para ver los datos originales.

Podemos decodificar estas cadenas para comprender mejor la estructura de JWT.

El siguiente es el encabezado decodificado del token. El encabezado es metainformación sobre el token. No nos dice mucho para ayudar a construir nuestra comprensión básica, por lo que no entraremos en detalles al respecto.

{
  "alg": "HS256",
  "typ": "JWT"
}

Carga útil

La carga útil es de mucho más interés. La carga útil puede incluir cualquier dato que desee, pero puede incluir solo una identificación de usuario si el propósito de su token es la autenticación de acceso a la API.

{
  "userId": "1234567890"
}

Es importante tener en cuenta que la carga útil no es segura. Cualquiera puede decodificar el token y ver exactamente qué hay en la carga útil. Por esa razón, generalmente incluimos una identificación en lugar de información de identificación confidencial como el correo electrónico del usuario.

Aunque esta carga útil es todo lo que se necesita para identificar a un usuario en una API, no proporciona un medio de autenticación. Alguien podría encontrar fácilmente su ID de usuario y falsificar un token si eso es todo lo que se incluye.

Esto nos lleva a la firma, que es la pieza clave para autenticar el token.

algoritmos hash

Antes de explicar cómo funciona la firma, debemos definir qué es un algoritmo hash.

Para empezar, es una función para transformar una cadena en una nueva cadena llamada picadillo. Por ejemplo, supongamos que queremos codificar la cadena “Hola, mundo”. Aquí está el resultado que obtendríamos usando el algoritmo hash SHA256:

4ae7c3b6ac0beff671efa8cf57386151c06e58ca53a78d83f36107316cec125f

La propiedad más importante del hash es que no puede usar el algoritmo hash para identificar la cadena original mirando el hash.

Hay muchos tipos diferentes de algoritmos hash, pero SHA256 se usa comúnmente con JWT.

En otras palabras, nosotros no poder tome el hash anterior y descubra directamente que la cadena original era “Hola, mundo”. El hash es tan complicado que adivinar la cadena original sería inviable.

firma JWT

Entonces, volviendo a la estructura JWT, veamos ahora la tercera parte del token, la firma. Esto realmente necesita ser calculado:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  "secret string"
);

Aquí hay una explicación de lo que está pasando aquí:

En primer lugar, HMACSHA256 es el nombre de una función hash y toma dos argumentos; la cadena a hash y el “secreto” (definido a continuación).

En segundo lugar, la cadena que procesamos es el encabezado codificado en base 64, más la carga útil codificada en base 64.

En tercer lugar, el secreto es un dato arbitrario que solo el servidor lo sabe.

P. ¿Por qué incluir el encabezado y la carga útil en el hash de la firma?

Esto asegura que la firma sea única para este token en particular.

P. ¿Cuál es el secreto?

Para responder a esto, pensemos en cómo falsificarías una ficha.

Dijimos antes que no puedes determinar la entrada de un hash mirando la salida. Sin embargo, dado que sabemos que la firma incluye el encabezado y la carga útil, ya que son información pública, si conoce el algoritmo hash (pista: generalmente se especifica en el encabezado), podría generar el mismo hash.

Pero el secreto, que solo el servidor conoce, es no información pública. Incluirlo en el hash evita que alguien genere su propio hash para falsificar el token. Y dado que el hash oscurece la información utilizada para crearlo, nadie puede descubrir el secreto del hash tampoco.

El proceso de agregar datos privados a un hash se llama salazón y hace que descifrar el token sea casi imposible.

Proceso de autenticación

Así que ahora tiene una buena idea de cómo se crea un token. ¿Cómo lo usa para autenticar su API?

Acceso

Se genera un token cuando un usuario inicia sesión y se almacena en la base de datos con el modelo de usuario.

loginController.js

if (passwordCorrect) {
  user.token = generateToken(user.id);
  user.save();
}

El token luego se adjunta como el authorization encabezado en la respuesta a la solicitud de inicio de sesión.

loginController.js

if (passwordCorrect) {
  user.token = generateToken(user.id);
  user.save();
  res.headers("authorization", `Bearer ${token}`).send();
}

Solicitudes de autenticación

Ahora que el cliente tiene el token, puede adjuntarlo a cualquier solicitud futura para identificar al usuario de manera auténtica.

Cuando el servidor recibe una solicitud con un token de autorización adjunto, ocurre lo siguiente:

  1. Decodifica el token y extrae la ID de la carga útil.
  2. Busca al usuario en la base de datos con este ID.
  3. Compara el token de solicitud con el que está almacenado con el modelo del usuario. Si coinciden, el usuario está autenticado.

authMiddleware.js

const token = req.header.token;
const payload = decodeToken(token);
const user = User.findById(payload.id);
if (user.token = token) {
  // Authorized
} else {
  // Unauthorized
}

Saliendo de tu cuenta

Si el usuario cierra la sesión, simplemente elimine el token adjunto al modelo de usuario, y ahora el token ya no funcionará. Un usuario deberá iniciar sesión nuevamente para generar un nuevo token.

cerrar sesiónController.js

user.token = null;
user.save();

Envolver

Esa es una explicación muy básica de cómo puede proteger una API usando JSON Web Tokens. Espero que no te duela mucho la cabeza.

Sin embargo, hay mucho más sobre este tema, así que aquí hay algunas lecturas adicionales:


Conviértase en un desarrollador sénior de Vue en 2020.

Aprenda y domine lo que saben los profesionales sobre la creación, prueba e implementación de aplicaciones Vue de pila completa en nuestro curso más reciente.

Aprende más


Similar Posts

Leave a Reply

Your email address will not be published.