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

ZTXBAS JWT の検証

ユーザーがチャレンジを承認すると、ZTXBAS は短寿命の ES256 JWT を発行し、status 応答に含めます。署名だけでなく、期待した用途に対して有効なトークンであることも確認してください。

JWT の構成​

JWT はヘッダーとペイロードを持ちます。主な claims は次のとおりです。

  • sub、email:認証されたユーザー。
  • aud、origin:チャレンジの対象オリジン。
  • challenge_id:ログの相関に使える 1 回限りのチャレンジ ID。
  • iat、exp:発行時刻と有効期限(通常 5 分)。
  • iss:トークンを発行した ZTXBAS サーバー。
{ "alg": "ES256", "typ": "JWT", "kid": "abc123..." }
{
"iss": "https://ztxbas.example.com",
"sub": "alice@example.com",
"aud": "https://app.example.com",
"iat": 1704067200,
"exp": 1704067500,
"email": "alice@example.com",
"origin": "https://app.example.com",
"challenge_id": "c_abc123"
}

SDK による検証​

各 SDK は以下の順序で検証します。

  1. 3 つの base64url 部分を解析します。
  2. alg == ES256 を厳格に確認し、none を含む他方式を拒否します。
  3. JWKS キャッシュの kid を参照し、不明・期限切れなら /.well-known/jwks.json を再取得します(キャッシュ 5 分)。
  4. header + "." + payload の ES256 署名を検証します。
  5. exp が未来であることを確認します(時刻ずれ ±30 秒)。
  6. iat が未来に大きくずれていないことを確認します。
  7. expected_issuer が設定されていれば iss も照合します。

いずれかに失敗したトークンは拒否されます。

追加して確認すべき事項​

署名、期限、発行者の確認に加えて、バックエンドでは次の点を検証します。

origin が期待したオリジンと一致すること。 他サイト向けに正当に発行された JWT を流用されないようにします。

challenge_id が再利用されていないこと。 JWT はステートレスです。トークン窃取を想定する場合は、最近使ったチャレンジ ID を小規模な LRU キャッシュなどで管理し、再使用を拒否します。JWT を検証後すぐ独自セッション Cookie に交換・破棄する設計では、通常は必須ではありませんが、5 分間の有効期間に注意してください。

if claims.Origin != expectedOrigin {
return errors.New("token issued for a different origin")
}

SDK なしで検証する場合​

ES256 と JWKS に対応した標準的な JWT ライブラリを使用してください。公開鍵は /.well-known/jwks.json から取得できます。

kid は再起動しても安定しています。公開鍵の DER エンコードに対する SHA-256 の base64url 表現の先頭 16 文字です。同じ署名鍵を共有するサーバーは同じ kid を生成します。

{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"alg": "ES256",
"use": "sig",
"kid": "abc123...",
"x": "base64url...",
"y": "base64url..."
}
]
}

鍵ローテーション​

署名鍵をローテーションすると JWKS が複数鍵を返す場合があります。新しいトークンは最新鍵で署名され、旧トークンは通常 5 分以内の exp まで検証可能です。kid を尊重し未知の kid で JWKS を再取得すれば、利用側の特別な操作は不要です。

関連資料​