1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum Error {
8 #[error("network error: {0}")]
10 Network(String),
11
12 #[error("discovery error: {0}")]
14 Discovery(String),
15
16 #[error("jwks error: {0}")]
18 Jwks(String),
19
20 #[error("verification failed: {0}")]
22 Verification(String),
23
24 #[error("oauth error: {error} - {description:?}")]
26 OAuth {
27 error: String,
29 description: Option<String>,
31 },
32
33 #[error("invalid parameter: {0}")]
35 InvalidParam(&'static str),
36
37 #[error("server-only function called in browser")]
39 ServerOnly,
40
41 #[error("recent login required")]
43 RequireRecentLogin,
44
45 #[error("timeout")]
47 Timeout,
48
49 #[error("http client error: {0}")]
51 HttpClient(#[from] crate::http::HttpClientError),
52
53 #[error("json error: {0}")]
55 Json(#[from] serde_json::Error),
56
57 #[error("url parse error: {0}")]
59 UrlParse(#[from] url::ParseError),
60
61 #[error("base64 decode error: {0}")]
63 Base64(String),
64
65 #[error("jwt error: {0}")]
67 Jwt(String),
68
69 #[error("cache error: {0}")]
71 Cache(String),
72
73 #[error("missing configuration: {0}")]
75 MissingConfig(&'static str),
76
77 #[error("invalid state: {0}")]
79 InvalidState(String),
80}
81
82impl Error {
83 pub fn oauth(error: impl Into<String>, description: Option<String>) -> Self {
85 Self::OAuth { error: error.into(), description }
86 }
87
88 pub fn is_oauth_error(&self, code: &str) -> bool {
90 matches!(self, Self::OAuth { error, .. } if error == code)
91 }
92
93 pub fn requires_recent_login(&self) -> bool {
95 matches!(self, Self::RequireRecentLogin)
96 || self.is_oauth_error("login_required")
97 || self.is_oauth_error("interaction_required")
98 }
99
100 pub fn is_retryable(&self) -> bool {
102 matches!(self, Self::Network(_) | Self::Timeout | Self::Discovery(_) | Self::Jwks(_))
103 }
104}
105
106pub type Result<T> = std::result::Result<T, Error>;