fix(maestro): bind registry JWTs to issuer/audience to stop token confusion (NAP-266)
ci / rust (push) Failing after 6m0s
ci / rust (push) Failing after 6m0s
Cookie and pair-attach JWTs are signed with the same shared secret. Neither verifier bound the token's purpose, so a token minted for one could in principle validate as the other. - Add a canonical `REGISTRY_ISSUER` to maestro-protocol; registry re-exports it. - Auth cookies now carry `iss = maestro-registry` + a dedicated `aud = maestro-cookie`; `verify_cookie` binds both, so a pair-attach JWT (daemon-id audience) is rejected. - `PairAttachVerifier::verify` now binds `iss = REGISTRY_ISSUER`, rejecting any token not minted by the registry. Tests: pair-verifier rejects a foreign issuer; verify_cookie rejects a pair-attach JWT. Existing cookie + broker e2e flows unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -372,6 +372,12 @@ pub struct JwtClaims {
|
||||
pub iat: Option<i64>,
|
||||
}
|
||||
|
||||
/// `iss` claim baked into every registry-issued JWT (pair-attach credentials
|
||||
/// and auth cookies alike). Verifiers bind to it so a token minted for one
|
||||
/// purpose can't be replayed as another even though both share the signing
|
||||
/// secret (NAP-266).
|
||||
pub const REGISTRY_ISSUER: &str = "maestro-registry";
|
||||
|
||||
/// Pair-scoped attach credential. Issued by the registry inside
|
||||
/// [`AttachCandidates::jwt`]; verified by the target daemon for direct
|
||||
/// transports (T1/T2) and gated by `allow_inbound` after JWT verification.
|
||||
|
||||
Reference in New Issue
Block a user