1use alloc::string::String;
4#[cfg(feature = "ciborium")]
5use core::convert::Infallible;
6use core::fmt;
7
8#[cfg(feature = "ciborium")]
9pub(crate) type CborDeError<E = anyhow::Error> = ciborium::de::Error<E>;
10#[cfg(feature = "ciborium")]
11pub(crate) type CborSerError<E = Infallible> = ciborium::ser::Error<E>;
12
13#[derive(Debug)]
15#[non_exhaustive]
16pub enum ParseError {
17 InvalidTokenStructure,
22 InvalidBase64Encoding,
24 MalformedHeader(serde_json::Error),
26 UnsupportedContentType(String),
33}
34
35impl fmt::Display for ParseError {
36 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 Self::InvalidTokenStructure => formatter.write_str("invalid token structure"),
39 Self::InvalidBase64Encoding => write!(formatter, "invalid base64 decoding"),
40 Self::MalformedHeader(err) => write!(formatter, "malformed token header: {err}"),
41 Self::UnsupportedContentType(ty) => {
42 write!(formatter, "unsupported content type: {ty}")
43 }
44 }
45 }
46}
47
48impl core::error::Error for ParseError {
49 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
50 match self {
51 Self::MalformedHeader(err) => Some(err),
52 _ => None,
53 }
54 }
55}
56
57#[derive(Debug)]
59#[non_exhaustive]
60pub enum ValidationError {
61 AlgorithmMismatch {
63 expected: String,
65 actual: String,
67 },
68 InvalidSignatureLen {
70 expected: usize,
72 actual: usize,
74 },
75 MalformedSignature(anyhow::Error),
77 InvalidSignature,
79 MalformedClaims(serde_json::Error),
81 #[cfg(feature = "ciborium")]
83 #[cfg_attr(docsrs, doc(cfg(feature = "ciborium")))]
84 MalformedCborClaims(CborDeError),
85 NoClaim(Claim),
87 Expired,
89 NotMature,
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
95#[non_exhaustive]
96pub enum Claim {
97 Expiration,
99 NotBefore,
101}
102
103impl fmt::Display for Claim {
104 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
105 formatter.write_str(match self {
106 Self::Expiration => "exp",
107 Self::NotBefore => "nbf",
108 })
109 }
110}
111
112impl fmt::Display for ValidationError {
113 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
114 match self {
115 Self::AlgorithmMismatch { expected, actual } => write!(
116 formatter,
117 "token algorithm ({actual}) differs from expected ({expected})"
118 ),
119 Self::InvalidSignatureLen { expected, actual } => write!(
120 formatter,
121 "invalid signature length: expected {expected} bytes, got {actual} bytes"
122 ),
123 Self::MalformedSignature(err) => write!(formatter, "malformed token signature: {err}"),
124 Self::InvalidSignature => formatter.write_str("signature has failed verification"),
125 Self::MalformedClaims(err) => write!(formatter, "cannot deserialize claims: {err}"),
126 #[cfg(feature = "ciborium")]
127 Self::MalformedCborClaims(err) => write!(formatter, "cannot deserialize claims: {err}"),
128 Self::NoClaim(claim) => write!(
129 formatter,
130 "claim `{claim}` requested during validation is not present in the token"
131 ),
132 Self::Expired => formatter.write_str("token has expired"),
133 Self::NotMature => formatter.write_str("token is not yet ready"),
134 }
135 }
136}
137
138impl core::error::Error for ValidationError {
139 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
140 match self {
141 Self::MalformedSignature(err) => Some(err.as_ref()),
142 Self::MalformedClaims(err) => Some(err),
143 #[cfg(feature = "ciborium")]
144 Self::MalformedCborClaims(err) => Some(err),
145 _ => None,
146 }
147 }
148}
149
150#[derive(Debug)]
152#[non_exhaustive]
153pub enum CreationError {
154 Header(serde_json::Error),
156 Claims(serde_json::Error),
158 #[cfg(feature = "ciborium")]
160 #[cfg_attr(docsrs, doc(cfg(feature = "ciborium")))]
161 CborClaims(CborSerError),
162}
163
164impl fmt::Display for CreationError {
165 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
166 match self {
167 Self::Header(err) => write!(formatter, "cannot serialize header: {err}"),
168 Self::Claims(err) => write!(formatter, "cannot serialize claims: {err}"),
169 #[cfg(feature = "ciborium")]
170 Self::CborClaims(err) => write!(formatter, "cannot serialize claims into CBOR: {err}"),
171 }
172 }
173}
174
175impl core::error::Error for CreationError {
176 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
177 match self {
178 Self::Header(err) | Self::Claims(err) => Some(err),
179 #[cfg(feature = "ciborium")]
180 Self::CborClaims(err) => Some(err),
181 }
182 }
183}