hwt-demo

HWT(Hash Web Token)プロトコルの開発サーバーとシナリオデモ。

正規ドキュメント issues

HWTはステートレスなクロスドメイン認可トークンプロトコルである。任意のドメインが有効なissuer(発行者)となれる。トークンはissuerの公開鍵に到達できる誰でも検証可能であり、中央プロバイダーも当事者間の事前設定も不要だ。

デモ

これらのデモは利用を促進するためのものであり、包括的なリファレンスや教義ではない。プロトコルの上に、便利だがHWT仕様の一部ではないアプリケーション側の前提(revocation(失効)、委任API、サーバー規約)を重ねている。プロトコルが実際に保証する内容については、SPEC.mdを参照。共通の語彙についてはCONVENTIONS.mdを参照。

シナリオデモ

デプロイメントベースライン

実際のデプロイメントの出発点。自分のインフラに合わせて調整すること。これらのスクリプトはdemo_hosts.jsを使用せずensureServers()も呼び出さない — スタンドアロンで動作する。

HMACは単一パーティのデプロイメント(spec §2)向け。クロスオリジン検証やdelegation chainが必要な場合は非対称鍵のベースラインを使用すること。

必要環境

Deno — 他の依存関係なし。

クイックスタート — 2インスタンスのクロスオリジンデモ

# ターミナルA — 認証サーバー
deno run --allow-read=./ --allow-write=./ --allow-net=localhost ./http.js --port=8888 --hwt-keys=.hwt-keys-hosta.json

# ターミナルB — 第2サービス
deno run --allow-read=./ --allow-write=./ --allow-net=localhost ./http.js --port=8889 --hwt-keys=.hwt-keys-hostb.json

http://localhost:8888http://localhost:8889 を開く。

操作手順: Aでトークンを作成 → Bの「Verify External」に貼り付ける。Bはランタイムにentry AのJWKSを取得し、事前設定なしで署名を検証する。

--hwt-keysは鍵ペアをファイルに保存し、サーバー再起動後もトークンが有効に保たれる。インメモリ限定の鍵を使う場合は省略する。

デモスクリプト

各スクリプトはライブのサーバーインスタンスに対して完全なシナリオを実行する。demo_hosts.jsはサーバーが起動していない場合に自動的に起動する(ポート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

または先に別ターミナルでサーバーを手動起動し(上記クイックスタート参照)、その後デモスクリプトを実行する。


demo-agent-chain.js — AIエージェントのdelegation chain

ユーザーが認証サーバーで認証し、別サービス上のAIエージェントに権限を委任する。そのエージェントは第三のサービス上のサブエージェントにさらに委任する。最終トークンは完全な暗号的プロベナンスチェーン(del[])を保持し、外側トークンの署名によってカバーされる — 中央コーディネーターなしで改ざん防止を実現する。各リンクはそれぞれのissuerの公開鍵に対して独立に検証可能である。

ウォークスルー内容:ルートトークン生成 → クロスサーバー委任(hostB上のagent-1) → 第2ホップ委任(hostA上のagent-2) → 最終トークンのクロスオリジン検証 → ルートトークンのrevocationによるアプリケーション層でのチェーン無効化の確認。


demo-del-verify.js — del[]チェーン検証

プロトコル検証とアプリケーション層のrevocation確認の違いを示す — spec §12が明示的に区別する2つの異なる結果。

2ホップチェーン(user:alice → svc:agent-1 → svc:agent-2)を構築した後、aliceのルートトークンを失効させ、重要な瞬間を示す:プロトコル検証(/api/verify-external)は依然として成功する — 外側の署名は有効であり、これは正しい動作である。アプリケーション層のチェーン検証(/api/verify-chain)は失敗する — aliceのissuerのrevocationリストに失効したtidが含まれているためだ。外側トークンは再署名されていないため、その署名は有効なままである。無効化を検出できるのはアプリケーション層の状態確認のみである。

revocation確認はHWTの上に構築されたライブラリ機能である。Spec §13はrevocationを明示的にプロトコルスコープ外に置いている。プロトコルはチェーン構造と署名保証を定義する — それをどう活用するかは実装者が決定する。


demo-multiparty.js — マルチパーティ共同認可

2つの独立した組織がそれぞれ自組織のプリンシパルにapproverトークンを発行する。コーディネーターサービスは両トークンを各issuerのJWKSに対してクロスオリジンで検証する — 共有アイデンティティプロバイダーも組織間の事前合意も不要だ。両方の検証が成功した場合にのみ、コーディネーターは両承認者のアイデンティティを埋め込んだプライベートauthzスキーマ(spec §4.2)を使用して共同認可トークンを発行する。下流のサービスはコーディネータートークンを検証し、元のissuerに再接続せずにトークンのみからクォーラム記録を検査できる。

ここでdel[]が適用されない理由を示す:del[]はマルチペアレント形式を持たない線形なdelegation chainである。承認者のアイデンティティはauthz内のアプリケーションデータであり、プロトコルの委任記録ではない。また、一方のルートトークンをissuerで失効させても、コーディネーターのトークンストアには伝播しないことも示す — 各トークンの状態はそれぞれのissuerで管理される(spec §13)。


demo-federation.js — 自発的なクロスドメインフェデレーション

2つのHWT issuerは、双方が準拠したwell-knownエンドポイントを公開した時点で即座に相互運用可能になる — 登録も共有シークレットもフェデレーション協定も不要だ。このスクリプトは両方向でトークンを検証する:hostAのトークンをhostBで検証し、hostBのトークンをhostAで検証する。どちらのホストも相手のアイデンティティプロバイダーではなく、同じspec §12アルゴリズムが両方向で同一に実行される。

オリジンメタデータのdiscovery(/.well-known/hwt.json、spec §7)も示す:ドキュメントに含まれる内容、各フィールドの意味、ドキュメントが存在しない場合にverifierが行うこと(記載されたフィールドのデフォルト値を適用して継続 — spec §7)。


demo-mesh.js — サービスメッシュのdelegation chain

メッシュCA、mTLS、サービスメッシュなしで3サービスメッシュを横断するサービス間認証。認証サービス(hostA)からのユーザートークンがゲートウェイ(hostB)とバックエンド(hostC)を経由し、各ホップで前のサービスのJWKSに対して検証され再委任される。最終トークンはすべての中間ノードのdel[]エントリを保持し、トークン単体から独立に検証可能である。

authzは各ホップを通じて明示的に追跡される:viewer → viewer → viewer。ロールが変わらないのはspec §8.1が規範的であるためだ — 派生トークンのauthzは対象トークンのauthzと同等か、その厳格なサブセットでなければならない。ルートでのrevocationはアプリケーション層でチェーンを崩壊させる。


demo-partner-api.js — パートナーAPIアクセスとaudience binding

共有credentialなしのB2B APIインテグレーション。パートナー組織は利用側APIの/.well-known/hwt.jsonを読み込んで要件を確認し、その特定のAPIにバインドされたaudと、RBACスキーマとCONVENTIONS.mdの管轄語彙(GDPR/2.0/DE)を組み合わせた配列authz(spec §4.3)を持つトークンを発行する。利用側APIはクロスオリジンで検証し、アプリケーション層でaudience matchingを強制する(spec §12 step 9)。

audのミスマッチパスを明示的に示す:別サービスにバインドされた暗号的に有効なトークンが、署名検証通過後にアプリケーション層で拒否される。これはconfused deputy(仲介者の混乱)対策である(spec §11.4)。

合わせて示す内容:両方のスキーマが評価を満たすことを要求するauthz_evaluation: "all";管轄クレームを保持することはコンプライアンスではなく構造的な語彙に過ぎないというCONVENTIONS.mdの注意書き。


demo-edge.js — エッジでのステートレス検証

初回JWKS取得後、issuer(hostA)へのラウンドトリップなしで、同一トークンを2つのノード(hostB、hostC)で独立に検証する。

合わせて示す内容:kid未検出時の強制再取得とそのレート制限要件(spec §6、§11.7);事前登録済みissuerと未知issuerのセキュリティトレードオフ(spec §11.1、§11.2、§A.7)、および事前登録が推奨される本番環境構成である理由。


demo-revocation-strategies.js — revocation戦略ガイド

採用者からの最も一般的な実践的な質問:トークンのライフタイムを短縮するのはいつで、revocationシステムを構築するのはいつか?3つの戦略をライブトークンで示す:

デプロイメントコンテキスト(金融API、一般ユーザーセッション、内部サービス、長命なエージェント委任)をキーとした意思決定マトリックスを含み、spec §A.1のライフタイム範囲を使用する。採用者が戦略を選択する前に答えるべき4つの質問も含む。revocationを適切に選択されたライフタイムの代替ではなく補完として位置づける。


サーバーエンドポイント

http.jsは開発およびデモ用サーバーである。本番環境向けに堅牢化されていない。

プロトコルエンドポイント(仕様定義)

メソッド パス Spec 説明
GET /.well-known/hwt-keys.json §6 JWKS公開鍵 — クロスオリジン検証に必要
GET /.well-known/hwt.json §7 issuerメタデータ — authzスキーマ、audポリシー、委任深度、エンドポイント宣言

ライブラリ拡張エンドポイント

これらのエンドポイントはプロトコルの上に重ねられた動作を実装する。revocationと委任はアプリケーション上の問題であり、spec §13はこれらを明示的にプロトコルスコープ外に置いている。

メソッド パス 説明
GET /.well-known/hwt-revoked.json revocationリスト — hwt.jsonendpoints.revocationで宣言
POST /api/token/delegate 委任トークンを生成 — spec §8.1のチェーン構築ルールに従いdel[]を設定
POST /api/revoke tidまたはトークン文字列でトークンを失効
POST /api/revoke/clear revocationリストをクリア — 開発用便宜機能

検証エンドポイント

メソッド パス プロトコル アプリケーション層 説明
POST /api/verify ✓ 署名 + 有効期限 ✓ ローカルrevocation ローカル鍵で検証 + このサーバーのrevocationリストを確認
POST /api/verify-external ✓ 署名 + 有効期限 spec §12に従いクロスオリジンJWKSを取得して検証
POST /api/verify-chain ✓ 署名 + 有効期限 ✓ del[]全体のrevocation確認 検証 + 各del[]エントリのissuerのrevocationリストを取得
POST /api/decode payloadをデコード — 署名確認なし

これらのエンドポイントの違いは重要である。 /api/verify-externalはspec §12の検証アルゴリズムを実行する:署名、有効期限、del[]の構造的整合性(外側の署名によって保証)。これが準拠したverifierが実装するものである。/api/verify-chainはその上にアプリケーション層の状態確認を追加する — 各del[]エントリのissuerのrevocationリストを取得し、失効していないことを確認する。トークン発行後に委任者の認可が失効した場合、トークンはプロトコル検証を通過してもチェーン検証で失敗する可能性がある。この違いのステップバイステップのデモについてはdemo-del-verify.jsを参照。

トークンと鍵の管理

メソッド パス 説明
POST /api/token 署名済みトークンを生成
GET /api/info サーバーオリジン、kid、鍵タイプ
GET /api/keys 秘密鍵を含む完全な鍵設定 — 開発専用、絶対に公開しないこと
POST /api/keys/generate 鍵を再生成
POST /api/keys/import 以前の鍵設定を復元

引数

http.js

--port=8888          リスニングポート(デフォルト:8888)
--hwt-keys=filename  再起動をまたいで永続化するための鍵ファイルパス

--hwt-keysなしの場合、鍵はメモリ内に生成され再起動時に消失する。デフォルトではEd25519鍵が生成される。

関連

ライセンス

Apache License 2.0 — LICENSEを参照。