use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("network error: {0}")]
Network(String),
#[error("discovery error: {0}")]
Discovery(String),
#[error("jwks error: {0}")]
Jwks(String),
#[error("verification failed: {0}")]
Verification(String),
#[error("oauth error: {error} - {description:?}")]
OAuth {
error: String,
description: Option<String>,
},
#[error("invalid parameter: {0}")]
InvalidParam(&'static str),
#[error("server-only function called in browser")]
ServerOnly,
#[error("recent login required")]
RequireRecentLogin,
#[error("timeout")]
Timeout,
#[error("http client error: {0}")]
HttpClient(#[from] crate::http::HttpClientError),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("url parse error: {0}")]
UrlParse(#[from] url::ParseError),
#[error("base64 decode error: {0}")]
Base64(String),
#[error("jwt error: {0}")]
Jwt(String),
#[error("cache error: {0}")]
Cache(String),
#[error("missing configuration: {0}")]
MissingConfig(&'static str),
#[error("invalid state: {0}")]
InvalidState(String),
}
impl Error {
pub fn oauth(error: impl Into<String>, description: Option<String>) -> Self {
Self::OAuth { error: error.into(), description }
}
pub fn is_oauth_error(&self, code: &str) -> bool {
matches!(self, Self::OAuth { error, .. } if error == code)
}
pub fn requires_recent_login(&self) -> bool {
matches!(self, Self::RequireRecentLogin)
|| self.is_oauth_error("login_required")
|| self.is_oauth_error("interaction_required")
}
pub fn is_retryable(&self) -> bool {
matches!(self, Self::Network(_) | Self::Timeout | Self::Discovery(_) | Self::Jwks(_))
}
}
pub type Result<T> = std::result::Result<T, Error>;