1use crate::_prelude::*;
5
6pub type Result<T, E = Error> = std::result::Result<T, E>;
8
9type BoxError = Box<dyn std::error::Error + Send + Sync>;
10
11#[derive(Debug, ThisError)]
13pub enum Error {
14 #[error("{0}")]
16 Storage(
17 #[from]
18 #[source]
19 crate::store::StoreError,
20 ),
21 #[error(transparent)]
23 Config(#[from] ConfigError),
24 #[error(transparent)]
26 Transient(#[from] TransientError),
27 #[error(transparent)]
29 Transport(#[from] TransportError),
30
31 #[error("Token lacks the required scopes: {reason}.")]
33 InsufficientScope {
34 reason: String,
36 },
37 #[error("Provider rejected the grant: {reason}.")]
39 InvalidGrant {
40 reason: String,
42 },
43 #[error("Client authentication failed: {reason}.")]
45 InvalidClient {
46 reason: String,
48 },
49 #[error("Token has been revoked.")]
51 Revoked,
52}
53
54#[derive(Debug, ThisError)]
56pub enum ConfigError {
57 #[error("HTTP client could not be constructed.")]
59 HttpClientBuild {
60 #[source]
62 source: BoxError,
63 },
64 #[error(transparent)]
66 HttpRequest(#[from] oauth2::http::Error),
67 #[error("Descriptor contains an invalid URL.")]
69 InvalidDescriptor {
70 #[source]
72 source: oauth2::url::ParseError,
73 },
74 #[error("Redirect URI is invalid.")]
76 InvalidRedirect {
77 #[source]
79 source: oauth2::url::ParseError,
80 },
81
82 #[error("Descriptor `{descriptor}` does not enable the {grant} grant.")]
84 UnsupportedGrant {
85 descriptor: String,
87 grant: &'static str,
89 },
90 #[error("Cached token record is missing a refresh token.")]
92 MissingRefreshToken,
93 #[error("Requested scopes are invalid.")]
95 InvalidScope(#[from] crate::auth::ScopeValidationError),
96 #[error("Unable to build token record.")]
98 TokenBuild(#[from] crate::auth::TokenRecordBuilderError),
99 #[error("Token endpoint response is missing expires_in.")]
101 MissingExpiresIn,
102 #[error("The expires_in value exceeds the supported range.")]
104 ExpiresInOutOfRange,
105 #[error("The expires_in value must be positive.")]
107 NonPositiveExpiresIn,
108 #[error("Token endpoint changed scopes during the {grant} grant.")]
110 ScopesChanged {
111 grant: &'static str,
113 },
114}
115impl ConfigError {
116 pub fn http_client_build(src: impl 'static + Send + Sync + std::error::Error) -> Self {
118 Self::HttpClientBuild { source: Box::new(src) }
119 }
120}
121#[cfg(feature = "reqwest")]
122impl From<reqwest::Error> for ConfigError {
123 fn from(e: reqwest::Error) -> Self {
124 Self::http_client_build(e)
125 }
126}
127
128#[derive(Debug, ThisError)]
130pub enum TransientError {
131 #[error("Token endpoint returned an unexpected response: {message}.")]
133 TokenEndpoint {
134 message: String,
136 status: Option<u16>,
138 retry_after: Option<Duration>,
140 },
141 #[error("Token endpoint returned malformed JSON.")]
143 TokenResponseParse {
144 #[source]
146 source: serde_path_to_error::Error<serde_json::error::Error>,
147 status: Option<u16>,
149 },
150}
151#[derive(Debug, ThisError)]
153pub enum TransportError {
154 #[error("Network error occurred while calling the token endpoint.")]
156 Network {
157 #[source]
159 source: BoxError,
160 },
161 #[error("I/O error occurred while calling the token endpoint.")]
163 Io(#[from] std::io::Error),
164}
165impl TransportError {
166 pub fn network(src: impl 'static + Send + Sync + std::error::Error) -> Self {
168 Self::Network { source: Box::new(src) }
169 }
170}
171#[cfg(feature = "reqwest")]
172impl From<ReqwestError> for TransportError {
173 fn from(e: ReqwestError) -> Self {
174 Self::network(e)
175 }
176}