JSON Web Tokens
Tags: apidevelopment, api, token, jwt
Published: 2023-09-28 13:24:09

---
title: JSON Web Tokens
published: true
date: 2023-09-11 07:52:42 UTC
tags: apidevelopment,api,token,jwt
canonical_url: https://medium.com/all-you-need-is-clean-code/json-web-tokens-8bf2be3a8e4
---

#### API’s HTTP

#### Autenticación stateless basada en tokens

![](https://cdn-images-1.medium.com/max/1024/0*Y4-jq2xzr5oO1xTA)
_Photo by Jaye Haych on Unsplash_

[**Artículo escrito originalmente para Secture&Code**](https://secture.com/blog/json-web-tokens-jwt/)

### Autenticación y gestión de la sesión en APIs

Una de las principales características de las APIs es su condición de no tener estado, o por su término en inglés: de ser _stateless._

¿Qué implica esto? Pues que cada vez que se recibe una petición hay que volver a recrear el estado, incluida la sesión del usuario y su autenticación.

Puede parecer engorroso e innecesario, pero el hecho de ser _stateless_ es la característica principal que nos permite distribuir nuestra API en numerosos servidores sin necesidad de tener las sesiones persistidas de forma distribuida, lo cual **sí es un engorro innecesario.**

Obviamente, lo que no podemos hacer es solicitar al usuario que se autentique con cada petición que tenga que hacer al API, ya que esto sería una experiencia de uso nefasta. Para ello la solución más común es utilizar un sistema de autenticación basado en _tokens_. Veamos un par de ejemplos:

### **Tokens JWT**

Las siglas JWT provienen de _JSON Web Tokens_, y tal y como indica su nombre son unos _tokens_ basados en JSON. En realidad se trata de un estándar abierto que define una forma compacta y autocontenida para transmitir de forma segura información entre _backend_ y _frontend_ en forma de objeto JSON. Es segura porque esta información puede ser verificada y confiada ya que viene firmada digitalmente. Los _tokens_ JWT puede firmarse mediante el algoritmo **HMAC** o mediante un sistema **PKI** de claves públicas y privadas basadas en **RSA** o  **ECDSA.**

Opcionalmente estos _tokens_ pueden ser encriptados para ocultar la información durante la transmisión entre ambas partes. La firma del token permite verificar la integridad de la información contenida en él, y al realizarse mediante claves públicas y privadas, garantiza que solo el _holder_ de la clave privada ha podido emitir esa información.

Veamos un ejemplo de un _token _JWT:

![](https://cdn-images-1.medium.com/max/1024/1*L_fKVCxtqnJVljFjMwme0g.png)

Como se puede observar hay una estructura de tres elementos separados por puntos, tal que así:

```
xxxxxxxxxx.yyyyyyyyyy.zzzzzzzzzz
```

Cada una de estas secciones, codificadas en base64, son respectivamente:

- Header (Cabecera)
- Payload (Cuerpo)
- Signature (Firma)

Al realizar la decodificación de cada uno de estos elementos podemos ver el contenido de la cabecera y el cuerpo (la firma no va codificada):

![](https://cdn-images-1.medium.com/max/1024/1*4VBKHK0QL06M8D6Zjarqdg.png)

#### Header

Habitualmente la cabecera se compone de dos elementos: el tipo (_typ)_ que siempre en este caso es JWT, y el algoritmo que se usa para verificar la firma.

#### Payload

El cuerpo por su parte se compone de una serie de atributos (o _claims_) registrados (_sub, iss, exp, iat…)_ privados (_admin…)_ y públicos (_name)._

La lista de _claims_ registrados puede consultarse en la [especificación oficial](https://www.rfc-editor.org/rfc/rfc7519#section-4.1). Usualmente se componen solo de tres letras, ya que se supone que el _token_ debe de ser compacto. Veamos algunos de ellos:

- **iss:** _issuer_ o quién ha emitido el _token._
- **sub:** _subject_ o el motivo por el que se ha emitido el _token._
- **exp:** _expiration,_ la fecha en que expirará el _token_. Habitualmente en forma de _timestamp_.
- **iat:** _issued at,_ la fecha en que se emitió el _token_. Habitualmente en forma de _timestamp_.
- **aud:** _audience,_ el público a quien va dirigido el _token_.

Usualmente el _claim_ más usado es el de _exp_, ya que en muchos casos el resto son irrelevantes, pero la fecha de caducidad siempre es importante.

Los _claims_ privados son todos aquellos que nosotros queramos incluir: nombre, email, id… todo cuanto necesitemos.

Los _claims_ públicos pueden ser definidos por los usuarios de JWT, pero para evitar colisiones estos deben de estar registrados en el [_Registro IANA de JSON Web Tokens_](https://www.iana.org/assignments/jwt/jwt.xhtml)_._

#### Signature

Realizar la verificación de la firma es tan sencillo como utilizar la clave privada para firmar ese par de cabecera/cuerpo, y comprobar que coincide con la que nos envían para garantizar que el firmante está en posesión de la clave privada para realizar la firma.

### Uso del token

Tras realizar login con el API, esta nos devuelve un _token_ similar al que hemos visto antes, la forma de utilizar estos _tokens_ es incluirlos con la cabecera _Authorization_ de este modo:

```
**Authorization:** Bearer eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.jYW04zLDHfR1v7xdrW3lCGZrMIsVe0vWCfVkN2DRns2c3MN-mcp_-RE6TN9umSBYoNV-mnb31wFf8iun3fB6aDS6m_OXAiURVEKrPFNGlR38JSHUtsFzqTOj-wFrJZN4RwvZnNGSMvK3wzzUriZqmiNLsG8lktlEn6KA4kYVaM61_NpmPHWAjGExWv7cjHYupcjMSmR8uMTwN5UuAwgW6FRstCJEfoxwb0WKiyoaSlDuIiHZJ0cyGhhEmmAPiCwtPAwGeaL1yZMcp0p82cpTQ5Qb-7CtRov3N4DcOHgWYk6LomPR5j5cCkePAz87duqyzSMpCB0mCOuE3CU2VMtGeQ
```

La palabra clave _Bearer_ indica que es un token autocontenido. Mientras el token sea válido (el atributo _exp_ contiene la fecha de caducidad) el API nos dará acceso a la sesión del usuario logueado.

### Refresh Tokens

Habitualmente el TTL _(time to live)_ o duración del _token_, es relativamente corto, ya que cualquiera que tenga el token podría impersonar la sesión. El problema es que no podemos estar pidiéndole cada dos por tres al usuario que se autentique, por lo que tenemos que ser creativos y buscar una alternativa.

La alternativa preferida es el uso del _refresh token_. El _refresh_ _token_ es un _token_ que nos permite obtener un nuevo _token_ de sesión sin necesidad de volver a introducir los credenciales del usuario. Por normal general el _refresh token_ tiene una duración muy superior a la del _token_ de sesión, y es responsabilidad del _frontend_ almacenarlo de la manera más segura posible.

Al contrario que los _tokens_ de sesión, estos se guardan en base de datos y pueden invalidarse manualmente, por lo que si somos conscientes o sospechamos que hubo un robo del _token,_ podemos invalidarlos y dejar al atacante sin posibilidad de seguir utilizándolo.

Además de esto, podemos tomar precauciones extra, como asociarlo a una IP en concreto o cualquier otra medida que nos parezca apropiada.

### **Basic Auth**

Esta es una forma de autenticación totalmente desaconsejada, ya que implica almacenar temporalmente la contraseña del usuario para realizar la autenticación.

Básicamente consiste en realizar una codificación en _base64_ del nombre del usuario junto con su contraseña, separados por el carácter de los dos puntos y enviarlo en la cabecera _Authorization._

Supongamos que el usuario es admin@secture.com y la contraseña p4ssW0rD entonces la cadena a codificar sería:

```
admin@secture.com:p4ssW0rD
```

Daría como resultado:

```
YWRtaW5Ac2VjdHVyZS5jb206cDRzc1cwckQ=
```

Y la usaríamos de esta manera:

```
**Authorization:** Basic YWRtaW5Ac2VjdHVyZS5jb206cDRzc1cwckQ=
```

En este caso la palabra clave _Basic_ indicaría el tipo de autenticación.

Como se puede ver, es muy sencillo que un potencial atacante _esnife_ el tráfico y obtenga la contraseña de nuestro usuario con una simple decodificación del _token._

### Conclusión

Al tratar con APIs sin estado necesitamos hacer uso de algún método para recrear la sesión del usuario. Actualmente existen varias alternativas. Aquí hemos visto dos, pero solo recomendamos el uso de JWT, ya que es un estándar abierto, enfocado en la seguridad y la integridad de los datos y ampliamente usado en producción.

La autenticación básica es solo un remanente de épocas pasadas que está condenado a desaparecer, ya que es totalmente inseguro.

¡Desde Secture te animamos a dejar comentarios explicando qué otros medios usas para controlar las sesiones de los usuarios de tu API!

### Bibliografía:

- [JSON Web Tokens (JWT)](https://jwt.io/introduction)
- [Basic Access Authorization](https://en.wikipedia.org/wiki/Basic_access_authentication)

* * *