Skip to main content

pdk_jwt_lib/error/
jwt_error.rs

1// Copyright (c) 2026, Salesforce, Inc.,
2// All rights reserved.
3// For full license text, see the LICENSE.txt file
4
5//! # JWT Error Types
6//!
7//! This module contains error types used across the JWT library for handling
8//! various failure scenarios during JWT validation and processing.
9//!
10//! ## Primary types
11//!
12//! - [`JWTError`]: error type for JWT operations
13//! - [`JWTErrorEnumKind`]: error type for JWT operations (for testing purposes)
14
15use std::error::Error;
16use std::fmt;
17
18use base64::DecodeError;
19use jwt_compact::{ParseError, ValidationError};
20use pem::PemError;
21use serde_json::Error as SerdeError;
22
23/// Possible errors when handling the JWT validation lifecycle.
24#[derive(Clone, Debug, Eq, PartialEq)]
25pub enum JWTError {
26    /// Authorization header is missing from the request
27    AuthorizationHeaderNotPresent,
28    /// Bearer token format is malformed
29    BearerMalformed,
30    /// Bearer token is not present in the Authorization header
31    BearerNotPresent,
32    /// Audience claim validation failed
33    ClaimAudValidationFailed,
34    /// Required audience claim is missing
35    ClaimAudNotPresent,
36    /// Expiration claim validation failed
37    ClaimExpValidationFailed,
38    /// Required expiration claim is missing
39    ClaimExpNotPresent,
40    /// Not before claim validation failed
41    ClaimNbValidationFailed,
42    /// Required not before claim is missing
43    ClaimNbNotPresent,
44    /// Failed to parse ES (ECDSA) public key
45    EsPublicKeyParseFailed(String),
46    /// Expression processing failed during claim evaluation
47    ExpressionProcessingFailed(String),
48    /// Invalid key length for the specified algorithm
49    InvalidKeyLength(String),
50    /// Header handler is missing for key provision
51    KeyProvisionMissingHeaderHandler,
52    /// Key ID (kid) claim is missing
53    KidNotPresent,
54    /// Mandatory custom claim is missing or doesn't match expected value
55    MandatoryCustomClaimMismatchOrNotPresent,
56    /// Non-mandatory custom claim doesn't match expected value
57    NonMandatoryCustomClaimMismatch,
58    /// Failed to parse RSA public key
59    RsaPublicKeyParseFailed(String),
60    /// Failed to parse signing algorithm
61    SigningAlgorithmParseFailed,
62    /// Failed to parse signing key length
63    SigningKeyLengthParseFailed,
64    /// Failed to parse JWT token structure
65    TokenParseFailed(String),
66    /// General validation failed with specific reason
67    ValidationFailed(String),
68}
69
70#[cfg(test)]
71#[derive(Clone, Debug, Eq, PartialEq)]
72pub enum JWTErrorEnumKind {
73    AuthorizationHeaderNotPresent,
74    BearerMalformed,
75    BearerNotPresent,
76    ClaimAudValidationFailed,
77    ClaimAudNotPresent,
78    ClaimExpValidationFailed,
79    ClaimExpNotPresent,
80    ClaimNbValidationFailed,
81    ClaimNbNotPresent,
82    EsPublicKeyParseFailed,
83    ExpressionProcessingFailed,
84    InvalidKeyLength,
85    KeyProvisionMissingHeaderHandler,
86    KidNotPresent,
87    MandatoryCustomClaimMismatchOrNotPresent,
88    NonMandatoryCustomClaimMismatch,
89    RsaPublicKeyParseFailed,
90    SigningAlgorithmParseFailed,
91    SigningKeyLengthParseFailed,
92    TokenParseFailed,
93    ValidationFailed,
94}
95
96#[cfg(test)]
97impl From<&JWTError> for JWTErrorEnumKind {
98    fn from(value: &JWTError) -> Self {
99        match value {
100            JWTError::AuthorizationHeaderNotPresent => {
101                JWTErrorEnumKind::AuthorizationHeaderNotPresent
102            }
103            JWTError::BearerMalformed => JWTErrorEnumKind::BearerMalformed,
104            JWTError::BearerNotPresent => JWTErrorEnumKind::BearerNotPresent,
105            JWTError::ClaimAudValidationFailed => JWTErrorEnumKind::ClaimAudValidationFailed,
106            JWTError::ClaimAudNotPresent => JWTErrorEnumKind::ClaimAudNotPresent,
107            JWTError::ClaimExpValidationFailed => JWTErrorEnumKind::ClaimExpValidationFailed,
108            JWTError::ClaimExpNotPresent => JWTErrorEnumKind::ClaimExpNotPresent,
109            JWTError::ClaimNbValidationFailed => JWTErrorEnumKind::ClaimNbValidationFailed,
110            JWTError::ClaimNbNotPresent => JWTErrorEnumKind::ClaimNbNotPresent,
111            JWTError::EsPublicKeyParseFailed(_) => JWTErrorEnumKind::EsPublicKeyParseFailed,
112            JWTError::ExpressionProcessingFailed(_) => JWTErrorEnumKind::ExpressionProcessingFailed,
113            JWTError::InvalidKeyLength(_) => JWTErrorEnumKind::InvalidKeyLength,
114            JWTError::KeyProvisionMissingHeaderHandler => {
115                JWTErrorEnumKind::KeyProvisionMissingHeaderHandler
116            }
117            JWTError::KidNotPresent => JWTErrorEnumKind::KidNotPresent,
118            JWTError::MandatoryCustomClaimMismatchOrNotPresent => {
119                JWTErrorEnumKind::MandatoryCustomClaimMismatchOrNotPresent
120            }
121            JWTError::NonMandatoryCustomClaimMismatch => {
122                JWTErrorEnumKind::NonMandatoryCustomClaimMismatch
123            }
124            JWTError::RsaPublicKeyParseFailed(_) => JWTErrorEnumKind::RsaPublicKeyParseFailed,
125            JWTError::SigningAlgorithmParseFailed => JWTErrorEnumKind::SigningAlgorithmParseFailed,
126            JWTError::SigningKeyLengthParseFailed => JWTErrorEnumKind::SigningKeyLengthParseFailed,
127            JWTError::TokenParseFailed(_) => JWTErrorEnumKind::TokenParseFailed,
128            JWTError::ValidationFailed(_) => JWTErrorEnumKind::ValidationFailed,
129        }
130    }
131}
132
133impl fmt::Display for JWTError {
134    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135        write!(f, "{}", self.get_message())
136    }
137}
138
139impl Error for JWTError {}
140
141impl JWTError {
142    /// Get error message.
143    pub fn get_message(&self) -> &str {
144        match self {
145            JWTError::AuthorizationHeaderNotPresent => "JWT Token is required.",
146            JWTError::BearerMalformed => "Bearer malformed.",
147            JWTError::BearerNotPresent => "Invalid token. Not a bearer authorization header.",
148            JWTError::ClaimAudValidationFailed => "Invalid token. Aud claim validation error.",
149            JWTError::ClaimAudNotPresent => "Invalid token. Aud claim not present.",
150            JWTError::ClaimExpValidationFailed => "Invalid token. Exp claim validation error.",
151            JWTError::ClaimExpNotPresent => "Invalid token. Exp claim not present.",
152            JWTError::ClaimNbValidationFailed => "Invalid token. Nb claim validation error.",
153            JWTError::ClaimNbNotPresent => "Invalid token. Nb claim not present.",
154            JWTError::EsPublicKeyParseFailed(message) => message,
155            JWTError::ExpressionProcessingFailed(message) => message,
156            JWTError::InvalidKeyLength(message) => message,
157            JWTError::KeyProvisionMissingHeaderHandler => {
158                "Expected header handler for key provision."
159            }
160            JWTError::KidNotPresent => "Invalid token. Missing 'kid' header.",
161            JWTError::MandatoryCustomClaimMismatchOrNotPresent => {
162                "Invalid token. Mandatory custom claim mismatch or not present."
163            }
164            JWTError::NonMandatoryCustomClaimMismatch => {
165                "Invalid token. Non mandatory custom claim mismatch."
166            }
167            JWTError::RsaPublicKeyParseFailed(message) => message,
168            JWTError::TokenParseFailed(message) => message,
169            JWTError::SigningAlgorithmParseFailed => "Could not parse SigningAlgorithm from str",
170            JWTError::SigningKeyLengthParseFailed => "Could not parse SigningKeyLength from str",
171            JWTError::ValidationFailed(message) => message,
172        }
173    }
174}
175
176// Error mappings
177
178impl From<ValidationError> for JWTError {
179    fn from(e: ValidationError) -> Self {
180        match e {
181            ValidationError::MalformedClaims(err) => {
182                JWTError::TokenParseFailed(format!("Token parsing error: {err}"))
183            }
184            _ => JWTError::ValidationFailed(format!(
185                "Invalid token. JWT Policy validation error: {e}"
186            )),
187        }
188    }
189}
190
191impl From<jwt_simple::Error> for JWTError {
192    fn from(e: jwt_simple::Error) -> Self {
193        JWTError::ValidationFailed(format!("JWT Policy validation error: {e}"))
194    }
195}
196
197impl From<PemError> for JWTError {
198    fn from(e: PemError) -> Self {
199        JWTError::RsaPublicKeyParseFailed(format!("Public key parsing error: {e}"))
200    }
201}
202
203impl From<ParseError> for JWTError {
204    fn from(e: ParseError) -> Self {
205        JWTError::TokenParseFailed(format!("Token parsing error: {e}"))
206    }
207}
208
209impl From<DecodeError> for JWTError {
210    fn from(e: DecodeError) -> Self {
211        JWTError::TokenParseFailed(format!("Token decoding error: {e}"))
212    }
213}
214
215impl From<SerdeError> for JWTError {
216    fn from(e: SerdeError) -> Self {
217        JWTError::TokenParseFailed(format!("Token parsing error: {e}"))
218    }
219}