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