hwt-demo

Servidor de desarrollo y demostraciones de escenarios para el protocolo HWT (Hash Web Token).

documentación canónica issues

HWT es un protocolo de token de autorización sin estado y entre dominios. Cualquier dominio es un issuer (emisor) válido. Los tokens son verificables por cualquier parte que pueda acceder a las claves públicas del issuer — sin proveedor central, sin preconfiguración entre las partes.

Demostraciones

Estas demostraciones facilitan el uso — no son referencias exhaustivas ni dogma. Agregan suposiciones de la aplicación sobre el protocolo (revocation (revocación), APIs de delegación, convenciones de servidor) que son útiles pero no forman parte de la especificación de HWT. Para lo que el protocolo garantiza de forma normativa, consulta SPEC.md. Para el vocabulario compartido, consulta CONVENTIONS.md.

Demostraciones de escenarios

Bases de despliegue

Puntos de partida para despliegues reales. Adáptalos a tu infraestructura. Estos scripts no usan demo_hosts.js y no llaman a ensureServers() — son independientes.

HMAC es para despliegues de un solo servicio (especificación §2). Usa las bases asimétricas para cualquier caso que requiera verificación entre orígenes o delegation chains (cadenas de delegación).

Requisitos

Deno — sin otras dependencias.

Inicio rápido — demostración entre dos instancias de distintos orígenes

# Terminal A — servidor de autenticación
deno run --allow-read=./ --allow-write=./ --allow-net=localhost ./http.js --port=8888 --hwt-keys=.hwt-keys-hosta.json

# Terminal B — segundo servicio
deno run --allow-read=./ --allow-write=./ --allow-net=localhost ./http.js --port=8889 --hwt-keys=.hwt-keys-hostb.json

Abre http://localhost:8888 y http://localhost:8889.

Qué hacer: Crea un token en A → pégalo en "Verify External" en B. B obtiene el JWKS de A en tiempo de ejecución y verifica la firma sin ninguna configuración previa.

--hwt-keys guarda tu par de claves en un archivo para que los tokens sobrevivan a reinicios del servidor. Omítelo si solo quieres claves en memoria.

Scripts de demostración

Cada script ejecuta un escenario completo contra instancias de servidor en vivo. demo_hosts.js las inicia automáticamente si no están ya en ejecución (puertos 8888, 8889, 8880):

deno run -A demo-agent-chain.js
deno run -A demo-del-verify.js
deno run -A demo-multiparty.js
deno run -A demo-federation.js
deno run -A demo-mesh.js
deno run -A demo-partner-api.js
deno run -A demo-edge.js
deno run -A demo-revocation-strategies.js

O inicia los servidores manualmente en terminales separadas primero (ver el inicio rápido anterior) y luego ejecuta cualquier script de demostración.


demo-agent-chain.js — Cadena de delegación de agentes de IA

Un usuario se autentica con un servidor de autenticación y delega autoridad a un agente de IA en un servicio separado. Ese agente delega a un subagente en un tercer servicio. El token final lleva la cadena completa de procedencia criptográfica (del[]), cubierta por la firma del token externo — a prueba de manipulaciones sin necesidad de un coordinador central. Cada enlace es verificable de forma independiente contra las claves publicadas por el issuer correspondiente.

Recorre: creación del token raíz → delegación entre servidores (agent-1 en hostB) → segunda delegación (agent-2 en hostA) → verificación entre orígenes del token final → revocación del token raíz mostrando la invalidación de la cadena en la capa de aplicación.


demo-del-verify.js — Verificación de cadena del[]

Demuestra la distinción entre la verificación del protocolo y la comprobación de revocation en la capa de aplicación — dos resultados distintos que la especificación §12 separa explícitamente.

Tras construir una cadena de dos saltos (user:alice → svc:agent-1 → svc:agent-2), el script revoca el token raíz de alice y muestra el momento crítico: la verificación del protocolo (/api/verify-external) sigue siendo exitosa — la firma externa es válida, lo cual es correcto. La verificación de cadena en la capa de aplicación (/api/verify-chain) falla — la lista de revocation del issuer de alice contiene el tid revocado. El token externo no fue refirmado; su firma sigue siendo válida. Solo la comprobación de estado en la capa de aplicación detecta la invalidación.

La comprobación de revocation es una función de la biblioteca construida sobre HWT. La especificación §13 sitúa explícitamente la revocation fuera del alcance del protocolo. El protocolo define la estructura de la cadena y la garantía de firma — lo que hagas con ello es tu decisión.


demo-multiparty.js — Autorización conjunta entre múltiples partes

Dos organizaciones independientes emiten tokens de aprobación a sus propios principales. Un servicio coordinador verifica ambos tokens entre orígenes contra el JWKS de cada issuer — sin proveedor de identidad compartido, sin acuerdo previo entre las organizaciones. Solo cuando ambos se verifican, el coordinador emite un token de autorización conjunta usando un esquema authz privado (especificación §4.2) que incorpora las identidades de ambos aprobadores. Cualquier servicio posterior puede verificar el token del coordinador e inspeccionar el registro de quórum desde el propio token, sin volver a contactar a los issuers originales.

Demuestra por qué del[] no aplica aquí: es una cadena de delegación lineal sin forma multi-padre. Las identidades de los aprobadores son datos de aplicación en authz, no registros de delegación del protocolo. También muestra que revocar el token raíz de una parte en su issuer no se propaga al almacén de tokens del coordinador — el estado de cada token se gestiona en su propio issuer (especificación §13).


demo-federation.js — Federación espontánea entre dominios

Dos issuers de HWT interoperan en el momento en que ambos publican endpoints well-known conformes — sin registro previo, sin secretos compartidos, sin acuerdo de federación. Este script verifica tokens en ambas direcciones: token de hostA verificado en hostB, token de hostB verificado en hostA. Ningún host actúa como proveedor de identidad del otro; el mismo algoritmo de la especificación §12 se ejecuta de forma idéntica en ambas direcciones.

También demuestra el descubrimiento de metadatos del origen (/.well-known/hwt.json, especificación §7): qué contiene el documento, qué significa cada campo, y qué hacen los verifiers (verificadores) cuando está ausente (aplican los valores predeterminados documentados del campo y continúan — especificación §7).


demo-mesh.js — Cadena de delegación en malla de servicios

Autenticación de servicio a servicio a través de una malla de tres servicios sin una CA de malla, sin mTLS y sin una malla de servicios. Un token de usuario del servicio de autenticación (hostA) fluye a través de una pasarela (hostB) y un backend (hostC); cada salto se verifica contra el JWKS del servicio anterior y se redelegarelega. El token final lleva entradas del[] para cada intermediario — verificables de forma independiente desde el propio token.

authz se rastrea explícitamente en cada salto: viewer → viewer → viewer. El rol no cambia porque la especificación §8.1 es normativa — el authz del token derivado debe ser igual o un subconjunto estricto del authz del token de origen. La revocación en la raíz colapsa la cadena en la capa de aplicación.


demo-partner-api.js — Acceso a API de socios y vinculación de audiencia

Integración de API B2B sin credenciales compartidas. Una organización socia lee el /.well-known/hwt.json de la API consumidora para descubrir sus requisitos, luego emite un token con aud vinculado a esa API específica y authz en array (especificación §4.3) que combina un esquema RBAC con el vocabulario de jurisdicción de CONVENTIONS.md (GDPR/2.0/DE). La API consumidora verifica entre orígenes y luego aplica la correspondencia de audiencia en la capa de aplicación (especificación §12 paso 9).

El caso de coincidencia incorrecta de aud se demuestra explícitamente: un token criptográficamente válido vinculado a un servicio diferente es rechazado en la capa de aplicación tras pasar la verificación de firma. Esta es la mitigación del problema del ayudante confundido (especificación §11.4).

También cubre: authz_evaluation: "all" que requiere que ambos esquemas satisfagan la evaluación; y el aviso de CONVENTIONS.md de que llevar una declaración de jurisdicción no es cumplimiento normativo — es vocabulario estructural.


demo-edge.js — Verificación sin estado en el borde (edge)

El mismo token verificado de forma independiente en dos nodos (hostB, hostC) sin ningún viaje de ida al issuer (hostA) después de la obtención inicial del JWKS.

También cubre: la obtención forzada por kid no encontrado y su requisito de límite de tasa (especificación §6, §11.7); la compensación de seguridad entre issuer pre-registrado vs issuer desconocido (especificación §11.1, §11.2, §A.7) y por qué el pre-registro es la postura de producción recomendada.


demo-revocation-strategies.js — Guía de estrategias de revocación

La pregunta práctica más común para quienes adoptan el protocolo: ¿cuándo acortar la vida útil del token frente a construir un sistema de revocation? Se demuestran tres estrategias con tokens en vivo:

Incluye una matriz de decisión organizada por contexto de despliegue (API financiera, sesión de usuario general, servicio interno, delegación de agente de larga duración) usando rangos de vida útil de la especificación §A.1, y cuatro preguntas que quien adopte el protocolo debe responder antes de elegir una estrategia. Enmarca la revocation como un complemento a una vida útil bien elegida, no como sustituto de ella.


Endpoints del servidor

http.js es un servidor de desarrollo y demostración. No está reforzado para producción.

Endpoints del protocolo (definidos en la especificación)

Método Ruta Especificación Descripción
GET /.well-known/hwt-keys.json §6 Claves públicas JWKS — requeridas para verificación entre orígenes
GET /.well-known/hwt.json §7 Metadatos del issuer — esquemas authz, política aud, profundidad de delegación, declaraciones de endpoints

Endpoints de extensión de la biblioteca

Estos endpoints implementan comportamiento construido sobre el protocolo. La revocation y la delegación son responsabilidades de la aplicación — la especificación §13 las sitúa explícitamente fuera del alcance del protocolo.

Método Ruta Descripción
GET /.well-known/hwt-revoked.json Lista de revocation — declarada en hwt.json bajo endpoints.revocation
POST /api/token/delegate Crear un token delegado — llena del[] según las reglas de construcción de cadena de la especificación §8.1
POST /api/revoke Revocar un token por tid o por cadena de token
POST /api/revoke/clear Limpiar la lista de revocation — conveniencia para desarrollo

Endpoints de verificación

Método Ruta Protocolo Capa de aplicación Descripción
POST /api/verify ✓ firma + expiración ✓ revocation local Verificar contra claves locales + comprobar la lista de revocation de este servidor
POST /api/verify-external ✓ firma + expiración Obtener JWKS entre orígenes y verificar según la especificación §12
POST /api/verify-chain ✓ firma + expiración ✓ recorrido completo de revocation del[] Verificar + obtener la lista de revocation del issuer de cada entrada del[]
POST /api/decode Decodificar el payload — sin verificación de firma

La distinción entre estos endpoints es importante. /api/verify-external ejecuta el algoritmo de verificación de la especificación §12: firma, expiración, integridad estructural del del[] (garantizada por la firma externa). Esto es lo que implementa un verifier conforme. /api/verify-chain agrega comprobación de estado en la capa de aplicación — obtiene la lista de revocation del issuer de cada entrada de del[] y confirma que ninguna ha sido revocada. Un token puede pasar la verificación del protocolo y fallar la verificación de cadena si la autorización de un delegante fue revocada desde que se emitió el token. Consulta demo-del-verify.js para una demostración paso a paso de esta distinción.

Gestión de tokens y claves

Método Ruta Descripción
POST /api/token Crear un token firmado
GET /api/info Origen del servidor, kid, tipo de clave
GET /api/keys Configuración completa de claves incluyendo clave privada — solo para desarrollo, nunca exponer
POST /api/keys/generate Regenerar claves
POST /api/keys/import Restaurar una configuración de claves anterior

Argumentos

http.js

--port=8888          Puerto en el que escuchar (predeterminado: 8888)
--hwt-keys=filename  Ruta del archivo de claves para persistencia entre reinicios

Sin --hwt-keys, las claves se generan en memoria y se pierden al reiniciar. Por defecto se generan claves Ed25519.

Relacionado

Licencia

Apache License 2.0 — ver LICENSE.