cataclysm_jwt/
error.rs

1use std::fmt::Display;
2
3#[derive(Debug)]
4/// Sub error for JWT
5pub enum JWTError {
6    /// Occurs when JWT can be divided in more or less than three
7    JWTParts,
8    /// Happens when Header 'authorization' or 'Authorization is not present'
9    Header,
10    /// Happens when jwt payload is unable to be decoded or obtained.
11    PayloadField,
12    /// Happens when jwt header is unable to be decoded or obtained.
13    HeaderField,
14    /// Happens when no audience is in header and lax-security is not enabled.
15    NoAudience,
16    /// Happens when wrong audience was found on token and lax-security is not enabled.
17    WrongAudience,
18    /// Happens when no issuer was fopund on jwt
19    NoIss,
20    /// Happens when issuer differs from the one expected
21    WrongIss,
22    /// When algorithm does not match the one expected by the server
23    WrongAlgorithm,
24    /// When no algorithm was found on jwt
25    NoAlgorithm,
26    /// When jwt has expired
27    Expired,
28    /// When no expiration date was found
29    NoExp,
30    /// When iat or nbf comprises a time window that is yet ro happen
31    ToBeValid,
32    /// No iat was found on jwt
33    NoIat,
34    /// No nbf was found on jwt
35    NoNbf
36}
37
38#[derive(Debug)]
39/// Sub error for Keys creation and verification
40pub enum KeyError {
41    /// Error when trying to verify symmetric signature
42    Verification(ring::error::Unspecified),
43    /// Error when trying to verify assymmetric signature
44    RSASignature(rsa::signature::Error),
45    /// Error from RSA crate when trying to create a public key from modulus 'n' and exponent 'e'
46    RSA(rsa::Error),
47    /// Unable to convert JWK field to string
48    JWKField,
49    /// Did not find keys field on JWKS array
50    KeyField,
51    /// Kid not present on JWK
52    KidField,
53    /// Did not find key with kid specified
54    Kid,
55    /// Could not find primitive exponent 'e' on JWK
56    E,
57    /// Could not find primitive exponent 'n' on JWK
58    N
59}
60
61#[derive(Debug)]
62/// Sub error for creating session
63pub enum ConstructionError {
64    /// Did not find audience on JWTSession
65    Aud,
66    /// Did not find issuer on JWTSession
67    Iss,
68    /// Could not 
69    Keys
70}
71
72#[derive(Debug)]
73/// Main error
74pub enum Error {
75    /// Unable to parse timestamp for 'nbf', 'iat' or 'exp' fields
76    ParseTimestamp,
77    /// JWT sub error
78    JWT(JWTError),
79    /// Key sub error
80    Key(KeyError),
81    /// Parse error while converting 'nbf', 'iat' or 'exp' to integers to parse to timestamp
82    Parse(std::num::ParseIntError),
83    /// Decode base64 url safe error while parsing JWT
84    Decode(base64::DecodeError,&'static str),
85    /// Serde error while deserializing JWT parts into HashMaps
86    Serde(serde_json::Error),
87    /// Construction sub error
88    Construction(ConstructionError),
89    /// UTF8 error while decoding JWT from base64
90    UTF8(std::str::Utf8Error),
91    /// Reqwest error while trying to obtain JWK array (JWKS)
92    Reqwest(reqwest::Error),
93}
94
95impl Display for Error {
96
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        let string_to_write = match self {
99            Error::JWT(jwte) => {
100                match jwte {
101                    JWTError::JWTParts => String::from("JWT has more or less than three parts!"),
102                    JWTError::Header => String::from("Unable to find 'Authorization' header on request!"),
103                    JWTError::HeaderField => String::from("Unable to decode header field into string!"),
104                    JWTError::NoAlgorithm => String::from("Unable to determine algorithm based on header"),
105                    JWTError::PayloadField => String::from("Unable to decode jwt payload field to string!"),
106                    JWTError::WrongAlgorithm => String::from("Algorithm on verification key and algorithm on jwt do not match!"),
107                    JWTError::NoAudience => String::from("No Audience found on payload!"),
108                    JWTError::WrongAudience => String::from("Audience on payload and audience on server do not match!"),
109                    JWTError::NoIss => String::from("No Issuer found on payload!"),
110                    JWTError::WrongIss => String::from("Issuer on payload and issuer on server do not match!"),
111                    JWTError::Expired => String::from("Token expired"),
112                    JWTError::NoExp => String::from("No exp found on payload!"),
113                    JWTError::ToBeValid => String::from("validation time Window not valid yet!"),
114                    JWTError::NoIat => String::from("No iat found on payload!"),
115                    JWTError::NoNbf => String::from("No nbf found on payload!"),
116                }
117            },
118            Error::Decode(e,s) => {
119                format!("Decoding error: {}, With detail: {}",e,s)
120            },
121            Error::Key(ke) => {
122                match ke {
123                    KeyError::RSA(e) => format!("Unable to create public key from primitives 'n' and 'e'! {}",e),
124                    KeyError::Verification(e) => format!("Verification error! {}",e),
125                    KeyError::JWKField => String::from("Unable to decode jwk field!"),
126                    KeyError::KidField => String::from("Unable to find 'kid' field"),
127                    KeyError::KeyField => String::from("Unable to obtain 'key' field on jwk"),
128                    KeyError::E => String::from("Unable to obtain 'e' field on jwk"),
129                    KeyError::N => String::from("Unable to obtain 'n' field on jwk"),
130                    KeyError::Kid => String::from("Unable to find key with 'kid' provided"),
131                    KeyError::RSASignature(e) => format!("Error while verifying jwt with public key! {}",e)
132                }
133            },
134            Error::Construction(ce) => {
135                match ce {
136                    ConstructionError::Aud => format!("Missing audience field on constructor!"),
137                    ConstructionError::Iss => format!("Missing isuer field on constructor!"),
138                    ConstructionError::Keys => format!("Missing keys on constructor!")
139                }
140            }
141            Error::Reqwest(e) => format!("Reqest error while retrieving jwks! {}",e),
142            Error::Serde(e) => format!("Serde error! {}",e),
143            Error::Parse(e) => format!("Parseint error!° {}",e),
144            Error::ParseTimestamp => String::from("Unable to get timestamp from 'exp', 'iat' or 'nbf' fields!"),
145            Error::UTF8(e) => format!("UTF8 error! Unable to parse jwt into utf8 {}",e)
146        };
147
148        write!(f,"{}",string_to_write)
149    }
150
151}
152
153impl From<ring::error::Unspecified> for Error {
154    fn from(value: ring::error::Unspecified) -> Self {
155        Error::Key(KeyError::Verification(value))
156    }
157}
158
159impl From<reqwest::Error> for Error {
160    fn from(value: reqwest::Error) -> Self {
161        Error::Reqwest(value)
162    }
163}
164
165impl From<serde_json::Error> for Error {
166    fn from(value: serde_json::Error) -> Self {
167        Error::Serde(value)
168    }
169}
170
171impl From<rsa::Error> for Error {
172    fn from(value: rsa::Error) -> Self {
173        Error::Key(KeyError::RSA(value))
174    }
175}
176
177impl From<rsa::signature::Error> for Error {
178    fn from(value: rsa::signature::Error) -> Self {
179        Error::Key(KeyError::RSASignature(value))
180    }
181}
182
183impl From<std::num::ParseIntError> for Error {
184    fn from(value: std::num::ParseIntError) -> Self {
185        Error::Parse(value)
186    }
187}