Skip to main content

securitydept_oauth_resource_server/
error.rs

1use 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}