Vinculación de Token (Token Binding)

Autenticación Security Notes Jan 6, 2025 JAVASCRIPT

Definicion

Los bearer tokens tienen una debilidad fundamental: quien tenga el token puede usarlo. Si un atacante roba tu access token mediante un ataque de red, malware, o un servidor comprometido, puede hacerse pasar por ti hasta que ese token expire. Token Binding fue desarrollado para resolver este problema vinculando criptográficamente tokens a la conexión TLS específica para la que fueron emitidos.

El concepto es elegante: cuando estableces una conexión TLS segura, tu navegador genera un par de claves criptográficas único solo para esa conexión. Cuando solicitas un access token, ese token queda “vinculado” a tu par de claves. Después, cuando usas el token, debes probar que posees la clave privada. Un atacante que intercepte tu token no puede usarlo porque no tiene tu clave privada - el token es efectivamente inútil sin ella.

Es importante notar que el desarrollo de la especificación Token Binding se ha estancado en gran medida, y el soporte de navegadores sigue siendo limitado. La industria se ha movido hacia una alternativa más simple llamada DPoP (Demonstrating Proof-of-Possession), que logra objetivos similares con mejor soporte del ecosistema. DPoP crea una prueba firmada que acompaña cada uso del token, probando que aún controlas las claves. Si estás implementando tokens con prueba de posesión hoy, DPoP es usualmente el camino recomendado.

Ejemplo

Aplicaciones bancarias de alta seguridad: Las instituciones financieras que exploraron token binding querían asegurar que incluso si malware en la computadora de un usuario capturaba su access token, ese token no pudiera usarse desde una máquina diferente. El token solo funciona con las claves de la conexión TLS original.

Sistemas SSO empresariales: Las empresas que manejan datos sensibles consideraron token binding para prevenir ataques de robo de tokens. Incluso si un atacante interceptaba una cookie de sesión, no podían reproducirla desde su propio navegador.

Sistemas gubernamentales: Las aplicaciones gubernamentales de alta seguridad evaluaron token binding para cumplir requisitos estrictos de seguridad donde los bearer tokens regulares eran insuficientes.

Apps de banca móvil: Las apps financieras exploraron vincular criptográficamente tokens al dispositivo específico, para que tokens robados no pudieran usarse en dispositivos de atacantes.

Analogia

La Pulsera Vinculada a Huella Digital: Imagina una pulsera de parque acuático que no es solo una pulsera sino que está electrónicamente emparejada con tu huella digital. Incluso si alguien roba tu pulsera, no funcionará para ellos - las puertas de entrada verifican tanto la pulsera COMO tu huella digital. Token binding empareja el token con una prueba criptográfica que solo tú posees.

La Tarjeta de Acceso y el Escáner de Huella: Algunos edificios de alta seguridad requieren tanto una tarjeta de acceso COMO un escaneo de huella digital. Tener solo la tarjeta no es suficiente - necesitas probar que eres el titular autorizado. Token binding agrega este segundo factor a los bearer tokens.

La Cerradura de Dos Partes: Algunas bóvedas de banco requieren dos llaves sostenidas por diferentes personas. Ninguna llave sola puede abrir la bóveda. Token binding requiere tanto el token COMO prueba de posesión de la clave - ninguno solo otorga acceso.

El Ticket de Concierto Personalizado: Imagina tickets de concierto que solo funcionan cuando se escanean junto con tu foto de identificación que fue tomada cuando los compraste. Los tickets revendidos no funcionarían para otra persona. Los tokens vinculados solo funcionan para su titular original.

Code Example


// Flujo conceptual de Token Binding (implementación de bajo nivel)
// Nota: Token Binding no está ampliamente implementado y tiene soporte limitado de navegadores

// Cliente genera par de claves de token binding durante handshake TLS
const tokenBindingKeyPair = await crypto.subtle.generateKey(
  {
    name: 'ECDSA',
    namedCurve: 'P-256'
  },
  true,
  ['sign', 'verify']
);

// Cliente crea mensaje de Token Binding
const tokenBindingMessage = {
  tokenBindingType: 'provided',
  keyParameters: 'ecdsap256',
  signature: await signTokenBinding(tokenBindingKeyPair, tlsExporter)
};

// Incluir Token Binding ID en petición de token
const tokenRequest = await fetch('https://oauth.provider.com/token', {
  headers: {
    'Sec-Token-Binding': base64encode(tokenBindingMessage)
  },
  // ... otros parámetros de petición de token
});

// Servidor vincula token al Token Binding ID
// Token incluye claim 'cnf' (confirmation) con Token Binding ID

// Al usar token, cliente debe probar posesión de clave privada
// Servidor valida que firma coincida con Token Binding ID en token

// DPoP (Demonstrating Proof-of-Possession) es alternativa moderna:
const dpopProof = await generateDPoPProof({
  htm: 'GET',
  htu: 'https://api.example.com/resource',
  privateKey: clientPrivateKey
});

fetch('https://api.example.com/resource', {
  headers: {
    'Authorization': `DPoP ${accessToken}`,
    'DPoP': dpopProof
  }
});

Diagrama

sequenceDiagram
    participant Cliente as Cliente
    participant TLS as Capa TLS
    participant AuthServer as Servidor Auth
    participant API
    participant Atacante as Atacante

    Note over Cliente,TLS: Handshake TLS
    Cliente->>TLS: 1. Establecer conexión TLS
    TLS->>Cliente: 2. Generar par de claves único para esta conexión

    Note over Cliente: Token vinculado a claves de conexión TLS

    Cliente->>AuthServer: 3. Solicitar token + prueba de Token Binding
    AuthServer->>Cliente: 4. Token con vinculación (claim cnf)

    Cliente->>API: 5. Petición + Token + Prueba de posesión de clave
    API->>API: 6. Verificar firma del token
    API->>API: 7. Verificar vinculación con conexión TLS
    API->>Cliente: 8. Respuesta OK

    rect rgb(255, 230, 230)
        Note over Atacante: Token Robado!
        Atacante->>API: 9. Token robado (conexión TLS diferente)
        API->>API: 10. Token válido PERO vinculación falla!
        API->>Atacante: 11. 401 No autorizado
        Note over Atacante: No puede probar posesión de
claves de conexión TLS original end Note over Cliente,API: Token está CRIPTOGRÁFICAMENTE VINCULADO
a la conexión TLS original

Notas de Seguridad

SECURITY NOTES

CRÍTICO - …

Configuración y Validación:

  • La especificación Token Binding ya no está activamente desarrollada; considerar DPoP (Demonstrating Proof-of-Possession) como alternativa moderna.
  • Soporte limitado de navegadores y bibliotecas para Token Binding.
  • Requiere TLS 1.2+ con extensión de exporters.
  • Claves privadas nunca deben salir del dispositivo cliente.
  • Previene robo de tokens vía interceptación TLS, ataques man-in-the-middle y ataques de exportación de tokens.

Monitoreo y Protección:

  • No previene ataques si el dispositivo cliente está comprometido.
  • Agrega complejidad a la validación de tokens.
  • DPoP proporciona beneficios similares con mejor soporte del ecosistema.
  • Para nuevas implementaciones, usar DPoP sobre Token Binding.
  • Aún vulnerable a escenarios de cliente comprometido.

Estándares y RFCs