メインコンテンツまでスキップ

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/tcpLAN IPRP・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. 今回実行した処理​

  1. ユーザーに登録メールが送信され、ZTXBAS 認証アプリがスマートフォンにセットアップされました。アプリは UDP 9443 番を使用してサーバーと通信します。
  2. create_challenge が、オリジンの表示名を含む生体認証プッシュを端末へ送信しました。
  3. ユーザーが指紋または顔認証で承認しました。
  4. ZTXBAS が alice@example.com と https://app.example.com に結び付く ES256 JWT を発行しました。
  5. SDK が /.well-known/jwks.json から公開鍵を取得し、署名を検証して claims を返しました。

すぐに使えるクイックスタート​

各例は約 30 行で、同じエンドツーエンドの流れを試せます。

次に読む​