Skip to main content

modkit_auth/
errors.rs

1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum AuthError {
5    #[error("Authentication required: missing or invalid token")]
6    Unauthenticated,
7
8    #[error("Forbidden: insufficient permissions")]
9    Forbidden,
10
11    #[error("Invalid token: {0}")]
12    InvalidToken(String),
13
14    #[error("Token validation failed: {0}")]
15    ValidationFailed(String),
16
17    #[error("JWKS fetch failed: {0}")]
18    JwksFetchFailed(String),
19
20    #[error("Issuer mismatch: expected {expected}, got {actual}")]
21    IssuerMismatch { expected: String, actual: String },
22
23    #[error("Audience mismatch: expected {expected:?}, got {actual:?}")]
24    AudienceMismatch {
25        expected: Vec<String>,
26        actual: Vec<String>,
27    },
28
29    #[error("Token expired")]
30    TokenExpired,
31
32    #[error("Internal error: {0}")]
33    Internal(String),
34}
35
36#[cfg(feature = "axum-ext")]
37impl axum::response::IntoResponse for AuthError {
38    fn into_response(self) -> axum::response::Response {
39        use axum::http::StatusCode;
40        use axum::response::Json;
41        use serde_json::json;
42
43        let (status, message) = match self {
44            AuthError::Unauthenticated | AuthError::InvalidToken(_) | AuthError::TokenExpired => {
45                (StatusCode::UNAUTHORIZED, self.to_string())
46            }
47            AuthError::Forbidden => (StatusCode::FORBIDDEN, self.to_string()),
48            _ => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
49        };
50
51        let body = Json(json!({
52            "error": message,
53            "status": status.as_u16(),
54        }));
55
56        (status, body).into_response()
57    }
58}