pdk_token_introspection_lib/
error.rs1use thiserror::Error;
10
11#[non_exhaustive]
13#[derive(Error, Debug, PartialEq, Eq)]
14pub enum ConfigError {
15 #[error("Config error: the introspection URL is not valid")]
17 InvalidIntrospectionURL,
18 #[error("Config error: invalid authorization value")]
20 InvalidAuthorizationValue,
21 #[error("Config error: invalid consumer_by value")]
23 InvalidConsumerBy,
24}
25
26#[non_exhaustive]
28#[derive(Error, Debug, PartialEq, Eq)]
29pub enum ValidationError {
30 #[error("Token has expired.")]
32 TokenExpired,
33 #[error("Token has been revoked.")]
35 TokenRevoked,
36 #[error("The required scopes are not authorized")]
38 InvalidScopes,
39 #[error("Token is inactive.")]
41 TokenInactive,
42 #[error("The contract collector is not set")]
44 EmptyContractValidator,
45 #[error("Invalid Client")]
47 InvalidClientContracts {
48 name: Option<String>,
49 id: Option<String>,
50 },
51}
52
53#[non_exhaustive]
55#[derive(Error, Debug)]
56pub enum IntrospectionError {
57 #[error("Introspection request failed: {0}")]
59 RequestFailed(String),
60 #[error("Introspection HTTP error: status={status}, body={body}")]
62 HttpError { status: u32, body: String },
63 #[error("Failed to parse introspection response: {0}")]
65 ParseError(String),
66 #[error("Token validation failed: {0}")]
68 Validation(#[from] ValidationError),
69}
70
71#[derive(Error, Debug, PartialEq, Eq)]
73pub(crate) enum TokenError {
74 #[error("Unexpected error when deserializing cached value: {msg:}")]
76 BinaryDeserializeError { msg: String },
77 #[error("Unexpected error when serializing cached value: {msg:}")]
79 BinarySerializeError { msg: String },
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn config_error_messages_contain_context() {
88 let err = ConfigError::InvalidIntrospectionURL;
89 assert!(err.to_string().contains("introspection URL"));
90 assert!(!err.to_string().contains("authorization")); let err = ConfigError::InvalidAuthorizationValue;
93 assert!(err.to_string().contains("authorization"));
94 assert!(!err.to_string().contains("introspection URL")); }
96
97 #[test]
98 fn validation_errors_are_distinct() {
99 let expired = ValidationError::TokenExpired.to_string();
100 let revoked = ValidationError::TokenRevoked.to_string();
101 let scopes = ValidationError::InvalidScopes.to_string();
102
103 assert!(expired.contains("expired"));
105 assert!(revoked.contains("revoked"));
106 assert!(scopes.contains("scopes"));
107
108 assert_ne!(expired, revoked);
110 assert_ne!(revoked, scopes);
111 }
112
113 #[test]
114 fn token_error_messages_include_dynamic_fields() {
115 let err1 = TokenError::BinaryDeserializeError {
116 msg: "invalid data".to_string(),
117 };
118 let err2 = TokenError::BinaryDeserializeError {
119 msg: "other error".to_string(),
120 };
121 assert!(err1.to_string().contains("invalid data"));
122 assert!(err2.to_string().contains("other error"));
123 assert_ne!(err1.to_string(), err2.to_string()); let err3 = TokenError::BinarySerializeError {
126 msg: "serialize error".to_string(),
127 };
128 assert!(err3.to_string().contains("serialize error"));
129 assert_ne!(err1.to_string(), err3.to_string()); }
131}