ZTXBAS 導入ガイド
自分のマシンで約 15 分以内に JWT の検証まで試す入門ガイドです。本番導入ではなくローカルのデモを対象としています。同じ LAN 上のモバイルアプリと docker run を使い、TLS やリバースプロキシは設定しません。
本番環境向けの TLS 終端、Caddy/Let's Encrypt、Kubernetes などの構成は、動作を確認した後に deploy/README.md を参照してください。
1. ZTXBAS を起動
ZTXBAS は ghcr.io/corezt/ztxbas の署名済みコンテナーイメージとして配布されます。cosign による署名検証はデモでは任意ですが、本番導入前に実施することを推奨します(署名の検証手順)。
ユーザー登録時にメールを送るため、コンテナーから到達可能な SMTP リレーが必要です。
最初に配布されている設定ファイルをコピーし、LAN 上の IP アドレスを確認します。次のコード例に従って .env の各項目を設定してください。
ZTXBAS_PUBLIC_URL は登録リンクや QR コードに埋め込まれるため、スマートフォンから到達可能なアドレスが必要です。127.0.0.1 は使えません。
ZTXBAS_CONSOLE_LISTEN_ADDR=0.0.0.0:8080 はコンテナー内の待受アドレスです。ZTXBAS_ALLOW_INSECURE_CONSOLE=1 はこのデモ設定を許可するためのものです。ホスト側の -p 127.0.0.1:8080:8080 によって、管理コンソールはループバックに限定されます。
利用ポート:
| ポート | バインド先 | 用途 |
|---|---|---|
| 8443/tcp | LAN IP | RP・SDK 向け API |
| 8080/tcp | ループバック | 管理コンソール |
| 9443/udp | すべてのインターフェース | モバイルアプリ独自プロトコル。直接公開が必要で、HTTP プロキシでは転送できません |
別のマシンから SSH で管理する場合は -L 8080:localhost:8080 によるポート転送を利用し、ローカルの http://127.0.0.1:8080 にアクセスします。最後のコード例で /health を確認できます。
cp env.txt .env
ip -4 addr show | grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+' | grep -v '^127\.'
ZTXBAS_PUBLIC_URL=http://<lan-ip>:8443
ZTXBAS_CONSOLE_LISTEN_ADDR=0.0.0.0:8080
ZTXBAS_ALLOW_INSECURE_CONSOLE=1
ZTXBAS_SMTP_HOST=smtp.example.com
ZTXBAS_SMTP_PORT=587
ZTXBAS_SMTP_USER=your-smtp-user
ZTXBAS_SMTP_PASS=your-smtp-pass
ZTXBAS_SMTP_FROM=ztxbas@yourdomain.com
docker run --rm --name ztxbas \
--env-file .env \
-p <lan-ip>:8443:8443 \
-p 127.0.0.1:8080:8080 \
-p 9443:9443/udp \
-v ztxbas-data:/var/lib/ztxbas \
--cap-drop ALL --security-opt no-new-privileges \
--read-only --tmpfs /tmp:size=16m \
ghcr.io/corezt/ztxbas:latest
curl -s http://<lan-ip>:8443/health
# {"status":"ok","version":"1.0.0"}
2. ログインしてアプリを作成
アプリケーションとは認証を要求する RP(Relying Party)です。アプリには API リクエスト署名に使用する ID と HMAC シークレットが割り当てられます。
コンテナーログから初回管理者パスワードを取得し、127.0.0.1:8080 にアクセスしてログインします。初期パスワードは 1 回限りなので、画面の指示に従って変更してください。
コンソールの Applications → New application からアプリを作成すると、アプリ ID と HMAC シークレットが一度だけ表示されます。後から復元できないため、安全に保存してください。CLI を使う場合も以下の例で作成できます。
docker logs ztxbas 2>&1 | grep -i breakglass
docker exec ztxbas ztxbas app create "Quickstart App"
# Application created.
# ID: app_a1b2c3d4e5
# Name: Quickstart App
# HMAC secret: 5f6e7d8c9b0a...
3. オリジンを登録
オリジンは、アプリが認証を行う scheme://host[:port] 形式の URL です。利用者の端末に表示され、フィッシングへの対抗手段になります。
管理コンソールで先ほどのアプリを開き、https://app.example.com などのオリジンと表示名(例:Example App)を登録します。表示名はスマートフォンに表示されます。SDK で登録することもでき、その場合 HMAC 署名は SDK が処理します(HMAC 署名)。
4. ユーザー登録とチャレンジ作成
Go、Node/TypeScript、Python のいずれでも、ユーザー登録 → チャレンジ作成 → ポーリング → 検証済み JWT を受け取る流れは同じです。以下の 3 言語の例から選んでください。
本番環境では http://127.0.0.1:8443 を TLS 終端側の URL(例:https://ztxbas.example.com)に置き換えます。
Go
c, _ := ztxbas.New("http://127.0.0.1:8443", "app_a1b2c3d4e5", "5f6e7d8c9b0a...")
_, _ = c.RegisterUser(ctx, ztxbas.RegisterUserRequest{Email: "alice@example.com"})
ch, _ := c.CreateChallenge(ctx, ztxbas.CreateChallengeRequest{
UserEmail: "alice@example.com",
Origin: "https://app.example.com",
})
claims, _ := c.PollChallenge(ctx, ch.ChallengeID)
fmt.Println(claims.Email, claims.Origin)
Node/TypeScript
const c = new Client("http://127.0.0.1:8443", "app_a1b2c3d4e5", "5f6e7d8c9b0a...");
await c.registerUser({ email: "alice@example.com" });
const ch = await c.createChallenge({
user_email: "alice@example.com",
origin: "https://app.example.com",
});
const claims = await c.pollChallenge(ch.challenge_id);
console.log(claims.email, claims.origin);
Python
c = Client("http://127.0.0.1:8443", "app_a1b2c3d4e5", "5f6e7d8c9b0a...")
c.register_user("alice@example.com")
ch = c.create_challenge("alice@example.com", "https://app.example.com")
claims = c.poll_challenge(ch["challenge_id"])
print(claims.email, claims.origin)
5. 今回実行した処理
- ユーザーに登録メールが送信され、ZTXBAS 認証アプリがスマートフォンにセットアップされました。アプリは UDP 9443 番を使用してサーバーと通信します。
create_challengeが、オリジンの表示名を含む生体認証プッシュを端末へ送信しました。- ユーザーが指紋または顔認証で承認しました。
- ZTXBAS が
alice@example.comとhttps://app.example.comに結び付く ES256 JWT を発行しました。 - SDK が
/.well-known/jwks.jsonから公開鍵を取得し、署名を検証して claims を返しました。
すぐに使えるクイックスタート
各例は約 30 行で、同じエンドツーエンドの流れを試せます。