Skip to content

fix(test-auth-generator): canonical JWT payload field order + auth-failure logging - #58

Closed
somasekimoto wants to merge 1 commit into
mainfrom
fix/test-auth-generator-canonical-jwt
Closed

somasekimoto wants to merge 1 commit into
mainfrom
fix/test-auth-generator-canonical-jwt

Conversation

@somasekimoto

Copy link
Copy Markdown
Contributor

概要

generate-share-token が serde_json::json! で JWT payload を組んでいたため、キーがアルファベット順 (att, aud, exp, iat, iss, jti) にシリアライズされ、state node の JWT 署名検証と必ず不一致になっていた。state node は署名検証時にパース済み AuthTokenPayload 構造体を再シリアライズして署名対象を再構築する (signing_message()) ため、発行側のフィールド順が構造体宣言順 (iss, aud, exp, iat, jti, att) と一致しない限り検証が通らない。

payload を monas-account の DelegationClaims と同一フィールド順の serde 構造体に変更。

実機検証 (4ノード mesh)

この修正の上で、委譲 JWT による share 受信者 read を実機検証済み:

ケース 結果
受信者が委譲 JWT で member ノードから read ✅ 200 + data + version
受信者が委譲 JWT で非 member (relay) ノードから read ✅ 200 + data + version
同一 JWT の再利用 403 (jti nonce 記録によりシングルユース)
委譲なし受信者 / 別 content 向け JWT / 非 owner 発行 JWT ✅ すべて拒否

併せて

認証失敗が HTTP 応答で "Authentication failed" に redact される箇所で、詳細理由を tracing::warn に出すようにした。これがないと稼働ノードでの JWT 検証失敗の診断ができない(今回の調査でも必要だった)。

Follow-up (別issue化予定)

パース済み構造体の再シリアライズによる JWT 検証は brittle (フィールド順・空白・未知フィールドで正規トークンが壊れる)。from_jwt が保持しているワイヤ上のセグメントで検証すべき。

🤖 Generated with Claude Code

https://claude.ai/code/session_01PKq6ZoPVmhTZfv4oBeRF8J

… order; log redacted auth failures

generate-share-token built its JWT payload with serde_json::json!, whose
map keys serialize alphabetically (att, aud, exp, iat, iss, jti). The
state node verifies JWT signatures by re-serializing the parsed
AuthTokenPayload struct (field order iss, aud, exp, iat, jti, att), so
every token the tool minted failed signature verification — which is
also why the delegated-JWT read path had never been exercised end to
end. The payload is now a serde struct matching monas-account's
DelegationClaims field order, verified against a live 4-node mesh:
recipient reads with a delegated JWT succeed on both member and
non-member (relay) nodes.

Also logs the detailed reason (tracing::warn) when an authentication
failure is redacted to the generic HTTP "Authentication failed" body —
without it, diagnosing JWT verification failures on a running node is
guesswork.

Note for a follow-up: verifying JWTs by re-serializing parsed structs
is brittle (field order, whitespace, unknown fields all break genuine
tokens). Verification should use the original wire segments captured in
from_jwt instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKq6ZoPVmhTZfv4oBeRF8J
@somasekimoto

Copy link
Copy Markdown
Contributor Author

この修正は PR #56 に取り込みました (#56 側で main → #54 → #56 の取り込みを行った上で cherry-pick: b031e93)。実機検証の結果・経緯はこの PR の説明と #56 本文を参照してください。

@somasekimoto
somasekimoto deleted the fix/test-auth-generator-canonical-jwt branch July 25, 2026 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant