ppoppo_token/engine/shared_error.rs
1//! Profile-shared JOSE wire-format errors.
2//!
3//! Scope: errors emitted by the engine submodules whose enforcement
4//! axis is JWS/JOSE structural — algorithm whitelist (M01-M06), header
5//! attack surface (M07-M16a), serialization shape (M31-M34, segment
6//! count, base64url, JSON unique keys), plus the structural rejections
7//! `engine::verify` runs before any submodule (oversize, JSON-form,
8//! JWE).
9//!
10//! NOT in scope: registered-claim semantics (M17-M30 — exp/aud/iss/iat/
11//! sub/jti/cat/client_id). Those are profile-aware: RFC 9068 requires
12//! `cat`/`client_id`; OIDC requires `nonce`. Each profile owns its
13//! claims-validation pipeline and its claims-error variants. When
14//! id_token's `check_claims` lands (Phase 10.x), variant naming will
15//! parallel access_token's intentionally — the *errors* are structurally
16//! similar but the *enforcement contracts* are not, and forcing them
17//! through one shared enum would obscure that distinction.
18//!
19//! Variants map to mitigation IDs in
20//! `0context/STANDARDS_JWT_DETAILS_MITIGATION_PPOPPO.md` §A, §B, §D.
21
22#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
23pub enum SharedAuthError {
24 // ── A. Algorithm (M01-M06) ────────────────────────────────────────────
25 #[error("M01: alg=none rejected")]
26 AlgNone,
27 #[error("M02: algorithm outside whitelist")]
28 AlgNotWhitelisted,
29 #[error("M03: HMAC algorithm rejected")]
30 AlgHmacRejected,
31 #[error("M04: RSA algorithm rejected")]
32 AlgRsaRejected,
33 #[error("M05: ECDSA algorithm rejected")]
34 AlgEcdsaRejected,
35
36 // ── B. Header (M07-M16a) ──────────────────────────────────────────────
37 #[error("M07: jku header rejected")]
38 HeaderJku,
39 #[error("M08: x5u header rejected")]
40 HeaderX5u,
41 #[error("M09: jwk header rejected")]
42 HeaderJwk,
43 #[error("M10: x5c header rejected")]
44 HeaderX5c,
45 #[error("M11: crit header rejected")]
46 HeaderCrit,
47 #[error("M12: kid missing or unknown")]
48 KidUnknown,
49 #[error("M13: typ mismatch")]
50 TypMismatch,
51 #[error("M14: nested JWS rejected")]
52 NestedJws,
53 #[error("M15: JWE rejected")]
54 JwePayload,
55 #[error("M16: extra header params")]
56 HeaderExtraParam,
57 #[error("M16a: b64=false rejected")]
58 HeaderB64False,
59
60 // ── D. Serialization (M31-M34) ────────────────────────────────────────
61 #[error("M31: JWS JSON serialization rejected — Compact only")]
62 JwsJsonRejected,
63 #[error("M32: JSON object contains duplicate keys")]
64 DuplicateJsonKeys,
65 #[error("M33: segment contains non-URL-safe base64 characters")]
66 LaxBase64,
67 #[error("M34: token exceeds maximum size")]
68 OversizedToken,
69
70 // ── Parse / structural ────────────────────────────────────────────────
71 #[error("token is not a JWS Compact serialization")]
72 NotJwsCompact,
73 #[error("header is not valid JSON")]
74 HeaderUnparseable,
75 #[error("payload is not valid JSON")]
76 PayloadUnparseable,
77}