libauth_rs/
error.rs

1use thiserror::Error;
2
3/// Authentication result type
4pub type AuthResult<T> = Result<T, AuthError>;
5
6/// Authentication and authorization errors
7#[derive(Error, Debug, Clone)]
8pub enum AuthError {
9    #[error("Invalid token: {message}")]
10    InvalidToken {
11        message: String,
12        provider: Option<String>,
13    },
14
15    #[error("Token expired")]
16    TokenExpired { provider: Option<String> },
17
18    #[error("Provider not configured: {provider}")]
19    ProviderNotConfigured { provider: String },
20
21    #[error("Network error: {message}")]
22    NetworkError {
23        message: String,
24        provider: Option<String>,
25    },
26
27    #[error("Configuration error: {message}")]
28    ConfigurationError { message: String },
29
30    #[error("JWT decode error: {message}")]
31    JwtError {
32        message: String,
33        provider: Option<String>,
34    },
35
36    #[error("Authentication required")]
37    AuthenticationRequired,
38
39    #[error("Authorization failed: {0}")]
40    AuthorizationError(String),
41
42    #[error("Insufficient permissions: {0}")]
43    InsufficientPermissions(String),
44
45    #[error("User not found: {0}")]
46    UserNotFound(String),
47
48    #[error("Provider error: {0}")]
49    ProviderError(String),
50
51    #[error("Unsupported operation: {0}")]
52    UnsupportedOperation(String),
53
54    #[error("Internal error: {0}")]
55    InternalError(String),
56
57    #[error("Unknown error: {message}")]
58    Unknown {
59        message: String,
60        provider: Option<String>,
61    },
62}
63
64impl AuthError {
65    /// Get the provider associated with this error
66    pub fn provider(&self) -> Option<&str> {
67        match self {
68            AuthError::InvalidToken { provider, .. } => provider.as_deref(),
69            AuthError::TokenExpired { provider } => provider.as_deref(),
70            AuthError::NetworkError { provider, .. } => provider.as_deref(),
71            AuthError::JwtError { provider, .. } => provider.as_deref(),
72            AuthError::Unknown { provider, .. } => provider.as_deref(),
73            _ => None,
74        }
75    }
76
77    /// Add provider context to the error
78    pub fn with_provider(mut self, provider: impl Into<String>) -> Self {
79        match &mut self {
80            AuthError::InvalidToken { provider: p, .. } => *p = Some(provider.into()),
81            AuthError::TokenExpired { provider: p } => *p = Some(provider.into()),
82            AuthError::NetworkError { provider: p, .. } => *p = Some(provider.into()),
83            AuthError::JwtError { provider: p, .. } => *p = Some(provider.into()),
84            AuthError::Unknown { provider: p, .. } => *p = Some(provider.into()),
85            _ => {}
86        }
87        self
88    }
89}
90
91// Conversions from common error types
92#[cfg(feature = "authentication")]
93impl From<reqwest::Error> for AuthError {
94    fn from(err: reqwest::Error) -> Self {
95        AuthError::NetworkError {
96            message: err.to_string(),
97            provider: None,
98        }
99    }
100}
101
102#[cfg(feature = "authentication")]
103impl From<jsonwebtoken::errors::Error> for AuthError {
104    fn from(err: jsonwebtoken::errors::Error) -> Self {
105        AuthError::JwtError {
106            message: err.to_string(),
107            provider: None,
108        }
109    }
110}
111
112impl From<serde_json::Error> for AuthError {
113    fn from(err: serde_json::Error) -> Self {
114        AuthError::Unknown {
115            message: format!("JSON error: {}", err),
116            provider: None,
117        }
118    }
119}