HWT — Hash Web Token

Tokens de autenticación verificables entre cualquier par de servicios. Sin proveedor central.


import Hwtr from 'jsr:@hwt/hwtr-js'

const hwtr = await Hwtr.factory({}, keyConfig)
const result = await hwtr.verify(token)

if (result.ok) {
    console.log(result.data)
    // sub "user:4503", authz { scheme: "RBAC/1.0.2", roles: ["editor"] }
}

Leer la especificación - Ver demostraciones - Obtener la biblioteca


formato del token

hwt.signature.key-id.expires.format.payload

Seis campos separados por puntos. La firma cubre la expiración, el formato y el payload en un único paso canónico. La verificación reconstruye esa entrada desde el token y la comprueba contra la clave publicada del issuer (emisor).

Payload decodificado — token de agente delegado, cadena de dos saltos:

{
  "iss": "https://agent-b.example.com",
  "sub": "svc:agent-b",
  "aud": "https://api.target.com",
  "tid": "tok-7c8d",
  "authz": { "scheme": "RBAC/1.0.2", "roles": ["editor"] },
  "del": [
    { "iss": "https://auth.example.com",    "sub": "user:4503",    "tid": "tok-a1b2" },
    { "iss": "https://agent-a.example.com", "sub": "svc:agent-a",  "tid": "tok-c3d4" }
  ]
}

El verifier (verificador) ve la cadena completa: el usuario delegó a agent-a, agent-a delegó a agent-b. El array del está cubierto por la firma externa — no puede ser manipulado después de la emisión. Las comprobaciones de estado en la capa de aplicación (revocation (revocación), validez de sesión) son responsabilidad de la aplicación consumidora en cada issuer.


Verificación

Issuers pre-registrados — recomendado para producción:

Carga las claves de los issuers de confianza al inicio. La verificación posterior es local — sin llamada de red por token.

import Hwtr from 'jsr:@hwt/hwtr-js'

// al inicio: crea una instancia con claves públicas de issuers de confianza
const hwtr = await Hwtr.factory({}, {
  type: 'Ed25519',
  keys: [],
  publicKeys: {
    'auth-key':    'BASE64URL_SPKI',   // de auth.example.com
    'partner-key': 'BASE64URL_SPKI'    // de partner.example.com
  }
})

// en tu manejador de solicitudes — sin llamada de red
const result = await hwtr.verify(token)
if (result.ok) {
    console.log(result.data)
    // sub "user:4503" authz { scheme: "RBAC/1.0.2", roles: ["editor"] }
}

Firma y ciclo completo:

// Genera las claves una vez, guárdalas de forma segura
const keyConfig = await Hwtr.generateKeys({ type: 'Ed25519' })

const hwtr = await Hwtr.factory({ expiresInSeconds: 3600 }, keyConfig)

// Firma
const token = await hwtr.create({
  sub: 'user:4503',
  authz: { scheme: 'RBAC/1.0.2', roles: ['editor'] }
})

// Verifica
const result = await hwtr.verify(token)
// result.ok, result.data, result.expires, result.error

La delegation chain (cadena de delegación)

DIAGRAMA DE FLUJO DE LA DELEGATION CHAIN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ┌────────────────────────────────────┐
  │  user:4503                         │──────────────► auth.example.com
  │  iss: auth.example.com             │                 publicación de claves
  │  tid: tok-a1b2                     │
  └────────────────────────────────────┘
                    │ delegado a
                    ▼
  ┌────────────────────────────────────┐
  │  svc:agent-a                       │──────────────► agent-a.example.com
  │  iss: agent-a.example.com          │                 publicación de claves
  │  tid: tok-c3d4                     │
  └────────────────────────────────────┘
                    │ delegado a
                    ▼
  ┌────────────────────────────────────┐
  │  svc:agent-b                       │──────────────► agent-b.example.com
  │  iss: agent-b.example.com          │                 obtención de clave + verificación de firma
  │  tid: tok-7c8d  (token externo)    │
  └────────────────────────────────────┘
                    │ presenta token
                    ▼
          api.target.com

  Verificación del protocolo (especificación §12):
    1. Verificar la firma de agent-b contra las claves de agent-b.example.com
    2. Confirmar la integridad estructural de del[] — cubierta por la firma externa
    3. Entregar el payload verificado a la aplicación

  Capa de aplicación (decisión de implementación):
    4. Comprobar el estado de tok-c3d4 en agent-a.example.com
    5. Comprobar el estado de tok-a1b2 en auth.example.com

  Ningún paso contacta a un servidor central.
  El array del está cubierto por la firma de agent-b —
  no puede ser manipulado después de la emisión.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Lo que HWT no contempla

Los límites explícitos importan en los protocolos de seguridad. Estos aspectos están fuera del alcance de HWT por diseño.

Estado del token y revocation. Si un token ha sido invalidado después de su emisión no es una propiedad de la cadena de bytes firmada. HWT define lo que un token garantiza estructuralmente; no define el ciclo de vida de la sesión ni la infraestructura de revocation. Las aplicaciones que necesitan invalidación inmediata mantienen su propio almacén de estado y lo comprueban en la capa de aplicación. Los tokens de corta duración son el mecanismo principal para acotar la exposición.

Emisión de tokens. Cómo un principal obtiene un token es un asunto entre el principal y el servicio emisor. WebAuthn/FIDO2 es un complemento natural para la fase de autenticación previa a la emisión — también soberano por dominio, sin proveedor central.

Evaluación de autorización. HWT lleva la declaración (roles: ["editor"]). Si editor permite una acción específica es decisión de la aplicación consumidora. OPA y Casbin son complementos naturales.

Vinculación de sesión. Los tokens de HWT son bearer credentials (credenciales portadoras). Para despliegues donde el robo de tokens es la amenaza principal, DPoP (RFC 9449) es una extensión de proof-of-possession compatible — sin cambios de formato en HWT requeridos.

Sistemas sin acceso a la red. HWT asume disponibilidad de red para key discovery (descubrimiento de claves). Los tokens vencidos no funcionan sin conexión. Este es el comportamiento correcto.

La razón: compromisos de protocolo más acotados producen afirmaciones de seguridad más precisas y responsabilidades más claras para quien integra. Cuando el límite es explícito, la aplicación sabe exactamente qué le corresponde.


Algoritmos · Codecs

Algoritmo Notas
Ed25519 Predeterminado recomendado. Firmas rápidas y pequeñas.
ECDSA P-256 Amplio soporte de hardware y HSM.
ECDSA P-384 Mayor margen de seguridad cuando se requiera.
HMAC Solo para un único servicio. No conforme para uso entre dominios.
Codec Identificador Notas
JSON j Base requerida. Todas las implementaciones.
JSON Extended jx Fechas, BigInt, arrays tipados, Maps, Sets. Importación experimental opcional.
CBOR, MessagePack community Codecs binarios. Ver CONVENTIONS.

Estado

Borrador v0.7. Estructura del protocolo estable desde 2026-04.

Pendiente: registro de URI well-known en IANA · semántica de alcance de intercambio de tokens

Código fuente en GitHub →


Empezar

Instalar la biblioteca JS:

import Hwtr from 'jsr:@hwt/hwtr-js'

Ejemplos funcionales (Deno, Node, Cloudflare Workers): hwt-demo →

Leer la especificación:

SPEC.md →

Implementaciones en otros lenguajes:

IMPLEMENTATIONS.md →

Contribuir:

CONTRIBUTING.md →


Apache License 2.0 · Copyright 2026 Jim Montgomery y los Contribuidores de HWT · github.com/hwt-protocol