1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, AuthError>;
7
8#[derive(Error, Debug)]
10pub enum AuthError {
11 #[error("Configuration error: {message}")]
13 Configuration { message: String },
14
15 #[error("Authentication method '{method}' error: {message}")]
17 AuthMethod { method: String, message: String },
18
19 #[error("Token error: {0}")]
21 Token(#[from] TokenError),
22
23 #[error("Permission error: {0}")]
25 Permission(#[from] PermissionError),
26
27 #[error("Storage error: {0}")]
29 Storage(#[from] StorageError),
30
31 #[error("Network error: {0}")]
33 Network(#[from] reqwest::Error),
34
35 #[error("JSON error: {0}")]
37 Json(#[from] serde_json::Error),
38
39 #[error("JWT error: {0}")]
41 Jwt(#[from] jsonwebtoken::errors::Error),
42
43 #[error("Rate limit exceeded: {message}")]
45 RateLimit { message: String },
46
47 #[error("MFA error: {0}")]
49 Mfa(#[from] MfaError),
50
51 #[error("Device flow error: {0}")]
53 DeviceFlow(#[from] DeviceFlowError),
54
55 #[error("OAuth provider error: {0}")]
57 OAuthProvider(#[from] OAuthProviderError),
58
59 #[error("User profile error: {message}")]
61 UserProfile { message: String },
62
63 #[error("Invalid credential: {credential_type} - {message}")]
65 InvalidCredential { credential_type: String, message: String },
66
67 #[error("Authentication timeout after {timeout_seconds} seconds")]
69 Timeout { timeout_seconds: u64 },
70
71 #[error("Provider '{provider}' is not configured or supported")]
73 ProviderNotConfigured { provider: String },
74
75 #[error("Cryptography error: {message}")]
77 Crypto { message: String },
78
79 #[error("Validation error: {message}")]
81 Validation { message: String },
82
83 #[error("Internal error: {message}")]
85 Internal { message: String },
86}
87
88#[derive(Error, Debug)]
90pub enum TokenError {
91 #[error("Token has expired")]
92 Expired,
93
94 #[error("Token is invalid")]
95 Invalid { message: String },
96
97 #[error("Token not found")]
98 NotFound,
99
100 #[error("Token creation failed: {message}")]
101 CreationFailed { message: String },
102
103 #[error("Token refresh failed: {message}")]
104 RefreshFailed { message: String },
105
106 #[error("Token revocation failed: {message}")]
107 RevocationFailed { message: String },
108}
109
110#[derive(Error, Debug)]
112pub enum PermissionError {
113 #[error("Access denied: missing permission '{permission}' for resource '{resource}'")]
114 AccessDenied { permission: String, resource: String },
115
116 #[error("Role '{role}' not found")]
117 RoleNotFound { role: String },
118
119 #[error("Permission '{permission}' not found")]
120 PermissionNotFound { permission: String },
121
122 #[error("Invalid permission format: {message}")]
123 InvalidFormat { message: String },
124
125 #[error("Permission denied: {message}")]
126 Denied { action: String, resource: String, message: String },
127}
128
129#[derive(Error, Debug)]
131pub enum StorageError {
132 #[error("Connection failed: {message}")]
133 ConnectionFailed { message: String },
134
135 #[error("Operation failed: {message}")]
136 OperationFailed { message: String },
137
138 #[error("Serialization error: {message}")]
139 Serialization { message: String },
140
141 #[error("Storage backend not available")]
142 BackendUnavailable,
143}
144
145#[derive(Error, Debug)]
147pub enum MfaError {
148 #[error("MFA challenge expired")]
149 ChallengeExpired,
150
151 #[error("Invalid MFA code")]
152 InvalidCode,
153
154 #[error("MFA method not supported: {method}")]
155 MethodNotSupported { method: String },
156
157 #[error("MFA setup required")]
158 SetupRequired,
159
160 #[error("MFA verification failed: {message}")]
161 VerificationFailed { message: String },
162}
163
164#[derive(Error, Debug)]
166pub enum DeviceFlowError {
167 #[error("Authorization pending - user has not yet completed authorization")]
168 AuthorizationPending,
169
170 #[error("Slow down - polling too frequently")]
171 SlowDown,
172
173 #[error("Device code expired")]
174 ExpiredToken,
175
176 #[error("Access denied by user")]
177 AccessDenied,
178
179 #[error("Invalid device code")]
180 InvalidDeviceCode,
181
182 #[error("Unsupported grant type")]
183 UnsupportedGrantType,
184}
185
186#[derive(Error, Debug)]
188pub enum OAuthProviderError {
189 #[error("Invalid authorization code")]
190 InvalidAuthorizationCode,
191
192 #[error("Invalid redirect URI")]
193 InvalidRedirectUri,
194
195 #[error("Invalid client credentials")]
196 InvalidClientCredentials,
197
198 #[error("Insufficient scope: required '{required}', granted '{granted}'")]
199 InsufficientScope { required: String, granted: String },
200
201 #[error("Provider '{provider}' does not support '{feature}'")]
202 UnsupportedFeature { provider: String, feature: String },
203
204 #[error("Rate limited by provider: {message}")]
205 RateLimited { message: String },
206}
207
208impl AuthError {
209 pub fn config(message: impl Into<String>) -> Self {
211 Self::Configuration {
212 message: message.into(),
213 }
214 }
215
216 pub fn auth_method(method: impl Into<String>, message: impl Into<String>) -> Self {
218 Self::AuthMethod {
219 method: method.into(),
220 message: message.into(),
221 }
222 }
223
224 pub fn rate_limit(message: impl Into<String>) -> Self {
226 Self::RateLimit {
227 message: message.into(),
228 }
229 }
230
231 pub fn crypto(message: impl Into<String>) -> Self {
233 Self::Crypto {
234 message: message.into(),
235 }
236 }
237
238 pub fn validation(message: impl Into<String>) -> Self {
240 Self::Validation {
241 message: message.into(),
242 }
243 }
244
245 pub fn internal(message: impl Into<String>) -> Self {
247 Self::Internal {
248 message: message.into(),
249 }
250 }
251
252 pub fn access_denied(message: impl Into<String>) -> Self {
254 Self::Permission(PermissionError::Denied {
255 action: "access".to_string(),
256 resource: "resource".to_string(),
257 message: message.into(),
258 })
259 }
260
261 pub fn token(message: impl Into<String>) -> Self {
263 Self::Token(TokenError::Invalid {
264 message: message.into(),
265 })
266 }
267
268 pub fn device_flow(error: DeviceFlowError) -> Self {
270 Self::DeviceFlow(error)
271 }
272
273 pub fn oauth_provider(error: OAuthProviderError) -> Self {
275 Self::OAuthProvider(error)
276 }
277
278 pub fn user_profile(message: impl Into<String>) -> Self {
280 Self::UserProfile {
281 message: message.into(),
282 }
283 }
284
285 pub fn invalid_credential(credential_type: impl Into<String>, message: impl Into<String>) -> Self {
287 Self::InvalidCredential {
288 credential_type: credential_type.into(),
289 message: message.into(),
290 }
291 }
292
293 pub fn timeout(timeout_seconds: u64) -> Self {
295 Self::Timeout { timeout_seconds }
296 }
297
298 pub fn provider_not_configured(provider: impl Into<String>) -> Self {
300 Self::ProviderNotConfigured {
301 provider: provider.into(),
302 }
303 }
304}
305
306impl TokenError {
307 pub fn creation_failed(message: impl Into<String>) -> Self {
309 Self::CreationFailed {
310 message: message.into(),
311 }
312 }
313
314 pub fn refresh_failed(message: impl Into<String>) -> Self {
316 Self::RefreshFailed {
317 message: message.into(),
318 }
319 }
320
321 pub fn revocation_failed(message: impl Into<String>) -> Self {
323 Self::RevocationFailed {
324 message: message.into(),
325 }
326 }
327}
328
329impl PermissionError {
330 pub fn access_denied(permission: impl Into<String>, resource: impl Into<String>) -> Self {
332 Self::AccessDenied {
333 permission: permission.into(),
334 resource: resource.into(),
335 }
336 }
337
338 pub fn role_not_found(role: impl Into<String>) -> Self {
340 Self::RoleNotFound {
341 role: role.into(),
342 }
343 }
344
345 pub fn permission_not_found(permission: impl Into<String>) -> Self {
347 Self::PermissionNotFound {
348 permission: permission.into(),
349 }
350 }
351
352 pub fn invalid_format(message: impl Into<String>) -> Self {
354 Self::InvalidFormat {
355 message: message.into(),
356 }
357 }
358}
359
360impl StorageError {
361 pub fn connection_failed(message: impl Into<String>) -> Self {
363 Self::ConnectionFailed {
364 message: message.into(),
365 }
366 }
367
368 pub fn operation_failed(message: impl Into<String>) -> Self {
370 Self::OperationFailed {
371 message: message.into(),
372 }
373 }
374
375 pub fn serialization(message: impl Into<String>) -> Self {
377 Self::Serialization {
378 message: message.into(),
379 }
380 }
381}
382
383impl MfaError {
384 pub fn method_not_supported(method: impl Into<String>) -> Self {
386 Self::MethodNotSupported {
387 method: method.into(),
388 }
389 }
390
391 pub fn verification_failed(message: impl Into<String>) -> Self {
393 Self::VerificationFailed {
394 message: message.into(),
395 }
396 }
397}