openid_client/types/
errors.rs

1use serde::Deserialize;
2
3use super::HttpResponse;
4
5/// The return type of the methods used in this library
6pub type OidcReturnType<T> = Result<T, Box<OidcClientError>>;
7
8/// # ErrorWithResponse
9/// Returned error type from
10/// - [`OidcClientError::error()`] : T is [Error]
11/// - [`OidcClientError::type_error()`] : T is [TypeError]
12/// - [`OidcClientError::rp_error()`] : T is [RPError]
13/// - [`OidcClientError::op_error()`] : T is [StandardBodyError]
14pub struct ErrorWithResponse<T> {
15    /// The error
16    pub error: T,
17    /// Response
18    pub response: Option<HttpResponse>,
19}
20
21/// # StandardBodyError
22/// Error that is returned from the OIDC Server
23/// - [Error Response](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1)
24#[derive(Debug, Deserialize)]
25pub struct StandardBodyError {
26    /// Short title of the error
27    pub error: String,
28    /// Description of the error
29    pub error_description: Option<String>,
30    /// Error uri
31    pub error_uri: Option<String>,
32}
33
34/// # Error
35/// General Error returned when anything unexpected happens
36#[derive(Debug)]
37pub struct Error {
38    /// Error Message
39    pub message: String,
40}
41
42/// # TypeError
43/// Error returned when an arg is of Uuexpected value or type
44#[derive(Debug)]
45pub struct TypeError {
46    /// Error Message
47    pub message: String,
48}
49
50// TODO: add more context related fields
51
52/// # RPError
53/// Error related to the Client response expectations
54#[derive(Debug)]
55pub struct RPError {
56    /// Error Message
57    pub message: String,
58}
59
60/// # OidcClientError
61/// Error returned for all things related to `openid_client`
62#[derive(Debug)]
63pub enum OidcClientError {
64    /// [Error]
65    Error(Error, Option<HttpResponse>),
66    /// [TypeError]
67    TypeError(TypeError, Option<HttpResponse>),
68    /// [RPError]
69    RPError(RPError, Option<HttpResponse>),
70    /// [StandardBodyError]
71    OPError(StandardBodyError, Option<HttpResponse>),
72}
73
74impl OidcClientError {
75    /// Checks if the Error is [`OidcClientError::Error`]
76    pub fn is_error(&self) -> bool {
77        matches!(self, OidcClientError::Error(..))
78    }
79
80    /// Checks if the Error is [`OidcClientError::TypeError`]
81    pub fn is_type_error(&self) -> bool {
82        matches!(self, OidcClientError::TypeError(..))
83    }
84
85    /// Checks if the Error is [`OidcClientError::RPError`]
86    pub fn is_rp_error(&self) -> bool {
87        matches!(self, OidcClientError::RPError(..))
88    }
89
90    /// Checks if the Error is [`OidcClientError::OPError`]
91    pub fn is_op_error(&self) -> bool {
92        matches!(self, OidcClientError::OPError(..))
93    }
94
95    /// Returns the [`ErrorWithResponse<Error>`]
96    /// *Note: panics if called on the wrong enum*
97    pub fn error(self) -> ErrorWithResponse<Error> {
98        if let OidcClientError::Error(error, response) = self {
99            return ErrorWithResponse { error, response };
100        }
101        panic!("Not an Error");
102    }
103
104    /// Returns the [`ErrorWithResponse<TypeError>`]
105    /// *Note: panics if called on the wrong enum*
106    pub fn type_error(self) -> ErrorWithResponse<TypeError> {
107        if let OidcClientError::TypeError(error, response) = self {
108            return ErrorWithResponse { error, response };
109        }
110        panic!("Not a TypeError");
111    }
112
113    /// Returns the [`ErrorWithResponse<RPError>`]
114    /// *Note: panics if called on the wrong enum*
115    pub fn rp_error(self) -> ErrorWithResponse<RPError> {
116        if let OidcClientError::RPError(error, response) = self {
117            return ErrorWithResponse { error, response };
118        }
119        panic!("Not an RPError");
120    }
121
122    /// Returns the [`ErrorWithResponse<StandardBodyError>`]
123    /// *Note: panics if called on the wrong enum*
124    pub fn op_error(self) -> ErrorWithResponse<StandardBodyError> {
125        if let OidcClientError::OPError(error, response) = self {
126            return ErrorWithResponse { error, response };
127        }
128        panic!("Not an OPError");
129    }
130}
131
132impl OidcClientError {
133    pub(crate) fn new_error(message: &str, response: Option<HttpResponse>) -> Self {
134        OidcClientError::Error(
135            Error {
136                message: message.to_string(),
137            },
138            response,
139        )
140    }
141
142    pub(crate) fn new_type_error(message: &str, response: Option<HttpResponse>) -> Self {
143        OidcClientError::TypeError(
144            TypeError {
145                message: message.to_string(),
146            },
147            response,
148        )
149    }
150
151    pub(crate) fn new_rp_error(message: &str, response: Option<HttpResponse>) -> Self {
152        OidcClientError::RPError(
153            RPError {
154                message: message.to_string(),
155            },
156            response,
157        )
158    }
159
160    pub(crate) fn new_op_error(
161        error: String,
162        error_description: Option<String>,
163        error_uri: Option<String>,
164        response: Option<HttpResponse>,
165    ) -> Self {
166        OidcClientError::OPError(
167            StandardBodyError {
168                error,
169                error_description,
170                error_uri,
171            },
172            response,
173        )
174    }
175}