securitydept_oauth_resource_server/
error.rs1use http::StatusCode;
2use securitydept_creds::{CredsError, TokenFormat};
3use securitydept_oauth_provider::OAuthProviderError;
4use securitydept_utils::{
5 error::{ErrorPresentation, ToErrorPresentation, UserRecovery},
6 http::ToHttpStatus,
7};
8use snafu::Snafu;
9
10pub type OAuthResourceServerResult<T> = Result<T, OAuthResourceServerError>;
11
12#[derive(Debug, Snafu)]
13#[snafu(visibility(pub))]
14pub enum OAuthResourceServerError {
15 #[snafu(display("OAuth resource server configuration error: {message}"))]
16 InvalidConfig { message: String },
17
18 #[snafu(display("OAuth resource server metadata error: {message}"))]
19 Metadata { message: String },
20
21 #[snafu(display("OAuth resource server HTTP client error: {message}"))]
22 HttpClient { message: String },
23
24 #[snafu(display("OAuth resource server introspection error: {message}"))]
25 Introspection { message: String },
26
27 #[snafu(display("OAuth resource server token validation error: {source}"))]
28 TokenValidation { source: CredsError },
29
30 #[snafu(display("OAuth resource server policy violation: {message}"))]
31 PolicyViolation { message: String },
32
33 #[cfg(feature = "jwe")]
34 #[snafu(display("OAuth resource server JWE key error: {message}"))]
35 JweKey { message: String },
36
37 #[snafu(display(
38 "OAuth resource server does not support {token_format:?} access tokens in this verifier"
39 ))]
40 UnsupportedTokenFormat { token_format: TokenFormat },
41}
42
43impl From<OAuthProviderError> for OAuthResourceServerError {
44 fn from(value: OAuthProviderError) -> Self {
45 match value {
46 OAuthProviderError::InvalidConfig { message } => Self::InvalidConfig { message },
47 OAuthProviderError::Metadata { message } => Self::Metadata { message },
48 OAuthProviderError::HttpClient { message } => Self::HttpClient { message },
49 OAuthProviderError::Introspection { message } => Self::Introspection { message },
50 }
51 }
52}
53
54impl ToHttpStatus for OAuthResourceServerError {
55 fn to_http_status(&self) -> StatusCode {
56 match self {
57 OAuthResourceServerError::TokenValidation { .. }
58 | OAuthResourceServerError::PolicyViolation { .. }
59 | OAuthResourceServerError::UnsupportedTokenFormat { .. }
60 | OAuthResourceServerError::Introspection { .. } => StatusCode::UNAUTHORIZED,
61 OAuthResourceServerError::InvalidConfig { .. }
62 | OAuthResourceServerError::Metadata { .. }
63 | OAuthResourceServerError::HttpClient { .. } => StatusCode::INTERNAL_SERVER_ERROR,
64 #[cfg(feature = "jwe")]
65 OAuthResourceServerError::JweKey { .. } => StatusCode::INTERNAL_SERVER_ERROR,
66 }
67 }
68}
69
70impl ToErrorPresentation for OAuthResourceServerError {
71 fn to_error_presentation(&self) -> ErrorPresentation {
72 match self {
73 OAuthResourceServerError::TokenValidation { source } => source.to_error_presentation(),
74 OAuthResourceServerError::PolicyViolation { .. } => ErrorPresentation::new(
75 "access_denied",
76 "You do not have permission to access this resource.",
77 UserRecovery::None,
78 ),
79 OAuthResourceServerError::UnsupportedTokenFormat { .. }
80 | OAuthResourceServerError::Introspection { .. } => ErrorPresentation::new(
81 "auth_invalid_token",
82 "The access token is invalid or expired.",
83 UserRecovery::Reauthenticate,
84 ),
85 OAuthResourceServerError::InvalidConfig { .. }
86 | OAuthResourceServerError::Metadata { .. }
87 | OAuthResourceServerError::HttpClient { .. } => ErrorPresentation::new(
88 "auth_temporarily_unavailable",
89 "Authentication is temporarily unavailable.",
90 UserRecovery::Retry,
91 ),
92 #[cfg(feature = "jwe")]
93 OAuthResourceServerError::JweKey { .. } => ErrorPresentation::new(
94 "auth_temporarily_unavailable",
95 "Authentication is temporarily unavailable.",
96 UserRecovery::Retry,
97 ),
98 }
99 }
100}