Skip to main content

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}