Skip to main content

slim_auth/
errors.rs

1// Copyright AGNTCY Contributors (https://github.com/agntcy)
2// SPDX-License-Identifier: Apache-2.0
3
4use http::StatusCode;
5#[cfg(not(target_arch = "wasm32"))]
6use jsonwebtoken::jwk::KeyAlgorithm;
7
8#[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
9use spiffe::{
10    JwtSourceError, JwtSvidError, SpiffeIdError, TrustDomain, WorkloadApiError, X509SourceError,
11};
12
13use thiserror::Error;
14
15#[derive(Error, Debug)]
16pub enum AuthError {
17    // JWT errors
18    #[cfg(not(target_arch = "wasm32"))]
19    #[error("unsupported key algorithm: {0}")]
20    JwtUnsupportedKeyAlgorithm(KeyAlgorithm),
21    #[error("JWK does not contain the key algorithm (alg) field")]
22    JwtMissingKeyAlgorithm,
23    #[error("no private key available for signing")]
24    JwtMissingPrivateKey,
25    #[error("missing decoding key or autoresolve is disabled")]
26    JwtMissingDecodingKeyOrKeyResolver,
27    #[error("missing 'iss' in JWT claims")]
28    JwtMissingIssuer,
29    #[error("no key resolver available")]
30    JwtNoKeyResolver,
31    #[error("no static JWT token configured")]
32    JwtNoStaticTokenConfigured,
33    #[error("JWK format not supported for encoding (signing) keys")]
34    JwtJwkFormatNotSupportedForEncoding,
35    #[error("failed to fetch JWKS for issuer - status_code: {0}")]
36    JwtFetchJwksFailed(StatusCode),
37    #[error("StaticTokenProvider does not support custom claims")]
38    JwtStaticUnsupportedCustomClaims,
39
40    // OIDC/Oauth2 errors
41    #[error("token_endpoint not found in discovery document")]
42    OidcDiscoveryMissingTokenEndpoint,
43    #[error("OIDC discovery document missing 'issuer' field")]
44    OidcDiscoveryMissingIssuer,
45    #[error("OIDC discovery 'issuer' mismatch: expected '{expected}', got '{got}'")]
46    OidcDiscoveryIssuerMismatch { expected: String, got: String },
47    #[error("OIDC discovery field '{field}' URL '{url}' does not share origin with issuer")]
48    OidcDiscoveryUrlOriginMismatch { field: &'static str, url: String },
49    #[error("OIDC issuer URL must use https (got: {0})")]
50    OidcInsecureIssuerUrl(String),
51    #[error("key not found: {0}")]
52    OidcKeyNotFound(String),
53    #[error("kid is missing and multiple keys are available")]
54    OidcMissingKidWithMultipleKeys,
55    #[error("OIDC Token Provider does not support custom claims")]
56    OidcUnsupportedCustomClaims,
57    #[error("OAuth2 request error: {0}")]
58    OAuth2Request(Box<dyn std::error::Error + Send + Sync>),
59    #[error("Token endpoint error: status {status}, body: {body}")]
60    TokenEndpointError { status: u16, body: String },
61    #[error("Invalid client credentials")]
62    InvalidClientCredentials,
63    #[error("refresh token revoked or expired")]
64    RefreshTokenRevoked,
65
66    // hmac
67    #[error("hmac key is too short")]
68    HmacKeyTooShort,
69    #[error("hmac key is missing")]
70    HmacKeyMissing,
71
72    // Time
73    #[error("time error")]
74    TimeError(#[from] std::time::SystemTimeError),
75
76    // URL parsing
77    #[cfg(not(target_arch = "wasm32"))]
78    #[error("URL parse error")]
79    UrlParseError(#[from] url::ParseError),
80
81    // Header parsing
82    #[error("invalid header name")]
83    HeaderNameError(#[from] http::header::InvalidHeaderName),
84    #[error("invalid header value")]
85    HeaderValueError(#[from] http::header::InvalidHeaderValue),
86
87    // File watcher
88    #[cfg(not(target_arch = "wasm32"))]
89    #[error("file watcher error")]
90    FileWatcherError(#[from] crate::file_watcher::FileWatcherError),
91
92    // Token lifecycle
93    #[error("no token available")]
94    GetTokenError,
95    #[error("token invalid")]
96    TokenInvalid,
97    #[error("token malformed")]
98    TokenMalformed,
99    #[error("token invalid: missing subject claim")]
100    TokenInvalidMissingSub,
101    #[error("token invalid: replay")]
102    TokenInvalidReplay,
103    #[cfg(not(target_arch = "wasm32"))]
104    #[error("token invalid")]
105    JwtTokenInvalid(#[from] jsonwebtoken::errors::Error),
106    #[error("token invalid - missing or invalid exp claim")]
107    TokenInvalidMissingExp,
108
109    // HTTP / networking
110    #[cfg(not(target_arch = "wasm32"))]
111    #[error("HTTP request error")]
112    HttpError(#[from] reqwest::Error),
113
114    // JWKS / key resolution
115    #[error("failed to parse JWKS: {source}")]
116    JwksParse { source: serde_json::Error },
117    #[error("no suitable key found in JWKS for token header")]
118    JwksNoSuitableKey,
119    #[error("no cached JWKS for issuer: {issuer}")]
120    JwksCacheMiss { issuer: String },
121    #[error("openid discovery document missing jwks_uri field")]
122    OidcDiscoveryMissingJwksUri,
123    #[error("cached JWKS expired for issuer: {issuer}")]
124    JwksCacheExpired { issuer: String },
125
126    // SPIFFE / SPIRE integration
127    #[error("spire integration is not supported on Windows")]
128    SpireUnsupportedOnWindows,
129    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
130    #[error("serde error while encoding audience: {source}")]
131    SpiffeCustomClaimsSerialize { source: serde_json::Error },
132    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
133    #[error("spiffe error")]
134    SpiffeError(#[from] SpiffeIdError),
135    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
136    #[error("spiffe grpc error")]
137    SpiffeGrpcError(#[from] WorkloadApiError),
138    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
139    #[error("spiffe workload api unavailable")]
140    SpiffeWorkloadApiUnavailable,
141    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
142    #[error("spiffe x509 source error")]
143    SpiffeX509SourceError(#[from] X509SourceError),
144    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
145    #[error("spiffe jwt source error")]
146    SpiffeJwtSourceError(#[from] JwtSourceError),
147    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
148    #[error("jwt source not initialized")]
149    SpiffeJwtSourceNotInitialized,
150    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
151    #[error("missing jwt svid")]
152    SpiffeJwtSvidMissing,
153    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
154    #[error("missing jwt bundle")]
155    SpiffeJwtBundleMissing,
156    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
157    #[error("invalid JWT svid")]
158    SpiffeInvalidJwtSvid(#[from] JwtSvidError),
159    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
160    #[error("failed to fetch x509 SVID")]
161    SpiffeX509SvidMissing,
162    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
163    #[error("x509 source not initialized")]
164    SpiffeX509SourceNotInitialized,
165    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
166    #[error("x509 trust bundle not available: {0}")]
167    SpiffeX509BundleMissing(TrustDomain),
168    #[cfg(all(not(target_arch = "wasm32"), not(target_family = "windows")))]
169    #[error("spire x509 empty certificate chain")]
170    SpiffeX509EmptyCertChain,
171    // Serialization
172    #[error("JSON serialization error")]
173    JsonError(#[from] serde_json::Error),
174    #[error("base64 decode error")]
175    Base64DecodeError(#[from] base64::DecodeError),
176
177    // Rego policy
178    #[error("rego policy compilation failed: {0}")]
179    PolicyCompile(String),
180
181    // Operational
182    #[error("operation would block on async I/O; call async variant")]
183    WouldBlockOn,
184
185    // MLS
186    #[error("MLS is not supported by this provider")]
187    MlsNotSupported,
188    #[error("MLS signature key generation failed")]
189    MlsKeyGenerationFailed,
190    #[error("public key not found in identity claims")]
191    PublicKeyNotFound,
192    #[error("subject not found in identity claims")]
193    SubjectNotFound,
194}