broadcast_auth/error.rs
1//! Error type for the shared auth layer.
2
3/// Result alias for the crate's fallible operations.
4pub type Result<T> = core::result::Result<T, Error>;
5
6/// Errors produced by challenge parsing / response computation.
7#[non_exhaustive]
8#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
9pub enum Error {
10 /// The `WWW-Authenticate` challenge value could not be parsed (RFC 7235 /
11 /// RFC 2326 §14 for a Basic or Digest challenge).
12 #[error("failed to parse challenge: {0}")]
13 ChallengeParse(String),
14
15 /// The `Authorization` response value could not be computed from the
16 /// parsed challenge and credentials (e.g. an unsupported Digest
17 /// `algorithm`/`qop`).
18 #[error("failed to compute Authorization response: {0}")]
19 ResponseCompute(String),
20
21 /// [`crate::SignedUrlKeySet::new`] rejected a key whose secret is shorter
22 /// than the required minimum (issue #747) — a setup-time error, never
23 /// returned from request verification. The `kid` is included since this
24 /// is a config-diagnostic error, not an attacker-facing one.
25 #[error("signed-url key {kid:?} has a {actual}-byte secret, must be at least {min} bytes")]
26 SignedUrlKeyTooShort {
27 /// The offending key's id.
28 kid: String,
29 /// The required minimum secret length in bytes.
30 min: usize,
31 /// The offending secret's actual length in bytes.
32 actual: usize,
33 },
34
35 /// [`crate::SignedUrlKeySet::sign`] was asked to mint a token for a `kid`
36 /// the keyset has no secret for. Only reachable from the *signing* helper
37 /// (used by tests/operators minting URLs) — never from
38 /// [`crate::Verifier::verify`], which folds every signed-URL rejection
39 /// reason into the same [`crate::AuthResult::Unauthorized`] (see that
40 /// module's docs).
41 #[error("signed-url keyset has no key with kid {0:?}")]
42 UnknownSignedUrlKeyId(String),
43
44 /// A parameter that RFC 6750 (or `resource_metadata`) says MUST NOT repeat
45 /// appeared twice in one challenge.
46 #[error("duplicate parameter {name:?}")]
47 DuplicateParameter {
48 /// The offending parameter name (canonical, lower-cased).
49 name: String,
50 },
51
52 /// `resource_metadata` was not an absolute `https` URL (RFC 9728 §3).
53 #[error("invalid resource_metadata URL")]
54 InvalidResourceMetadata,
55
56 /// More challenges than [`crate::challenge::MAX_CHALLENGES`] were supplied.
57 #[error("more than {max} challenges")]
58 TooManyChallenges {
59 /// The cap.
60 max: usize,
61 },
62
63 /// A Bearer token cannot be carried in an `Authorization` header value —
64 /// it contains a byte outside visible ASCII (control character, CR/LF, or
65 /// non-ASCII) — so no header was produced rather than a corrupt or
66 /// injectable one.
67 #[error("bearer token is not a valid Authorization header value")]
68 InvalidBearerToken,
69
70 /// A URL's userinfo is not valid UTF-8 once percent-decoded. The message
71 /// carries the decoder's reason only, never the (encoded) credential.
72 #[error("invalid percent-encoded userinfo: {0}")]
73 InvalidUserinfo(String),
74
75 /// A URL cannot carry userinfo (a cannot-be-a-base URL), so the named
76 /// component (`"username"` / `"password"`) could not be removed.
77 #[error("failed to strip {0} from URL")]
78 UserinfoNotRemovable(&'static str),
79}