Skip to main content

rustauth_sso/
errors.rs

1use rustauth_core::plugin::PluginErrorCode;
2
3/// Provider lookup failed.
4pub const PROVIDER_NOT_FOUND: &str = "PROVIDER_NOT_FOUND";
5/// Provider registration conflicts with an existing provider id.
6pub const PROVIDER_EXISTS: &str = "PROVIDER_EXISTS";
7/// Provider id contains characters that are unsafe in paths or URLs.
8pub const INVALID_PROVIDER_ID: &str = "INVALID_PROVIDER_ID";
9/// Requested provider protocol type is not supported.
10pub const INVALID_PROVIDER_TYPE: &str = "INVALID_PROVIDER_TYPE";
11/// Domain verification was requested for an already verified provider.
12pub const DOMAIN_VERIFIED: &str = "DOMAIN_VERIFIED";
13/// Domain verification was attempted without a pending token.
14pub const NO_PENDING_VERIFICATION: &str = "NO_PENDING_VERIFICATION";
15/// SAML response parsing or validation failed.
16pub const SAML_INVALID_RESPONSE: &str = "SAML_INVALID_RESPONSE";
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19/// High-level category for stable public SSO error codes.
20pub enum SsoErrorCategory {
21    /// Invalid server or provider configuration.
22    Configuration,
23    /// Invalid user-controlled input.
24    UserInput,
25    /// Authenticated user is not authorized for the requested action.
26    Authorization,
27    /// Requested resource does not exist.
28    NotFound,
29    /// Identity provider runtime failure.
30    IdentityProviderRuntime,
31    /// Rejected input that may indicate an attack.
32    SuspectedAttack,
33    /// Feature or protocol behavior is intentionally unsupported.
34    Unsupported,
35    /// Unexpected internal failure.
36    Unexpected,
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40/// Descriptor for a stable SSO error code registered by the plugin.
41pub struct SsoErrorDescriptor {
42    /// Stable public error code.
43    pub code: &'static str,
44    /// Human-readable default message.
45    pub message: &'static str,
46    /// Error category for logging and metrics.
47    pub category: SsoErrorCategory,
48}
49
50const ERROR_DESCRIPTORS: &[SsoErrorDescriptor] = &[
51    descriptor(
52        PROVIDER_NOT_FOUND,
53        "SSO provider not found",
54        SsoErrorCategory::NotFound,
55    ),
56    descriptor(
57        "SAML_PROVIDER_NOT_FOUND",
58        "SAML provider not found",
59        SsoErrorCategory::NotFound,
60    ),
61    descriptor(
62        PROVIDER_EXISTS,
63        "SSO provider already exists",
64        SsoErrorCategory::UserInput,
65    ),
66    descriptor(
67        INVALID_PROVIDER_ID,
68        "Invalid provider id",
69        SsoErrorCategory::UserInput,
70    ),
71    descriptor(
72        INVALID_PROVIDER_TYPE,
73        "Invalid provider type",
74        SsoErrorCategory::UserInput,
75    ),
76    descriptor(
77        DOMAIN_VERIFIED,
78        "Domain has already been verified",
79        SsoErrorCategory::UserInput,
80    ),
81    descriptor(
82        NO_PENDING_VERIFICATION,
83        "No pending domain verification exists",
84        SsoErrorCategory::UserInput,
85    ),
86    descriptor(
87        "INVALID_ISSUER",
88        "Invalid issuer",
89        SsoErrorCategory::UserInput,
90    ),
91    descriptor(
92        "INVALID_DOMAIN",
93        "Invalid domain",
94        SsoErrorCategory::UserInput,
95    ),
96    descriptor(
97        "INVALID_CALLBACK_URL",
98        "Invalid callback URL",
99        SsoErrorCategory::UserInput,
100    ),
101    descriptor(
102        "INVALID_ERROR_CALLBACK_URL",
103        "Invalid error callback URL",
104        SsoErrorCategory::UserInput,
105    ),
106    descriptor(
107        "INVALID_NEW_USER_CALLBACK_URL",
108        "Invalid new-user callback URL",
109        SsoErrorCategory::UserInput,
110    ),
111    descriptor(
112        "DOMAIN_NOT_VERIFIED",
113        "Provider domain has not been verified",
114        SsoErrorCategory::Authorization,
115    ),
116    descriptor(
117        "INVALID_ORIGIN",
118        "Invalid request origin",
119        SsoErrorCategory::Authorization,
120    ),
121    descriptor(
122        "OIDC_PROVIDER_NOT_CONFIGURED",
123        "OIDC provider is not configured",
124        SsoErrorCategory::Configuration,
125    ),
126    descriptor(
127        "OIDC_CONFIG_NOT_CONFIGURED",
128        "OIDC config is not configured",
129        SsoErrorCategory::Configuration,
130    ),
131    descriptor(
132        "INVALID_OIDC_CONFIG",
133        "Invalid OIDC configuration",
134        SsoErrorCategory::Configuration,
135    ),
136    descriptor(
137        "SAML_PROVIDER_NOT_CONFIGURED",
138        "SAML provider is not configured",
139        SsoErrorCategory::Configuration,
140    ),
141    descriptor(
142        "SAML_CONFIG_NOT_CONFIGURED",
143        "SAML config is not configured",
144        SsoErrorCategory::Configuration,
145    ),
146    descriptor(
147        "INVALID_SAML_CONFIG",
148        "Invalid SAML configuration",
149        SsoErrorCategory::Configuration,
150    ),
151    descriptor(
152        "SAML_METADATA_TOO_LARGE",
153        "SAML metadata is too large",
154        SsoErrorCategory::Configuration,
155    ),
156    descriptor(
157        "SAML_UNKNOWN_ALGORITHM",
158        "Unknown SAML algorithm",
159        SsoErrorCategory::Configuration,
160    ),
161    descriptor(
162        "SAML_DEPRECATED_CONFIG_ALGORITHM",
163        "Deprecated SAML configuration algorithm",
164        SsoErrorCategory::Configuration,
165    ),
166    descriptor(
167        "SAML_ALGORITHM_NOT_ALLOWED",
168        "SAML algorithm is not allowed",
169        SsoErrorCategory::Configuration,
170    ),
171    descriptor(
172        "SAML_AUTHN_REQUEST_PRIVATE_KEY_REQUIRED",
173        "SAML AuthnRequest signing private key is required",
174        SsoErrorCategory::Configuration,
175    ),
176    descriptor(
177        "MISSING_SAML_RESPONSE",
178        "Missing SAML response",
179        SsoErrorCategory::IdentityProviderRuntime,
180    ),
181    descriptor(
182        "SAML_RESPONSE_TOO_LARGE",
183        "SAML response is too large",
184        SsoErrorCategory::IdentityProviderRuntime,
185    ),
186    descriptor(
187        "SAML_RESPONSE_NOT_SUCCESS",
188        "SAML response was not successful",
189        SsoErrorCategory::IdentityProviderRuntime,
190    ),
191    descriptor(
192        "SAML_SIGN_IN_FAILED",
193        "SAML sign-in failed",
194        SsoErrorCategory::IdentityProviderRuntime,
195    ),
196    descriptor(
197        "UNABLE_TO_EXTRACT_SAML_USER",
198        "Unable to extract SAML user",
199        SsoErrorCategory::IdentityProviderRuntime,
200    ),
201    descriptor(
202        "SAML_SESSION_NOT_FOUND",
203        "SAML session was not found",
204        SsoErrorCategory::IdentityProviderRuntime,
205    ),
206    descriptor(
207        SAML_INVALID_RESPONSE,
208        "Invalid SAML response",
209        SsoErrorCategory::SuspectedAttack,
210    ),
211    descriptor(
212        "INVALID_SAML_RESPONSE",
213        "Invalid SAML response",
214        SsoErrorCategory::SuspectedAttack,
215    ),
216    descriptor(
217        "REPLAYED_SAML_ASSERTION",
218        "Replayed SAML assertion",
219        SsoErrorCategory::SuspectedAttack,
220    ),
221    descriptor(
222        "INVALID_AUTHN_REQUEST_STATE",
223        "Invalid SAML AuthnRequest state",
224        SsoErrorCategory::SuspectedAttack,
225    ),
226    descriptor(
227        "INVALID_LOGOUT_REQUEST_STATE",
228        "Invalid SAML LogoutRequest state",
229        SsoErrorCategory::SuspectedAttack,
230    ),
231    descriptor(
232        "SAML_IN_RESPONSE_TO_PROVIDER_MISMATCH",
233        "SAML InResponseTo provider mismatch",
234        SsoErrorCategory::SuspectedAttack,
235    ),
236    descriptor(
237        "SAML_SIGNATURE_INVALID",
238        "Invalid SAML signature",
239        SsoErrorCategory::SuspectedAttack,
240    ),
241    descriptor(
242        "SAML_ASSERTION_SIGNATURE_REQUIRED",
243        "SAML assertion signature is required",
244        SsoErrorCategory::SuspectedAttack,
245    ),
246    descriptor(
247        "SAML_LOGOUT_REQUEST_SIGNATURE_REQUIRED",
248        "SAML LogoutRequest signature is required",
249        SsoErrorCategory::SuspectedAttack,
250    ),
251    descriptor(
252        "SAML_LOGOUT_RESPONSE_SIGNATURE_REQUIRED",
253        "SAML LogoutResponse signature is required",
254        SsoErrorCategory::SuspectedAttack,
255    ),
256    descriptor(
257        "SAML_DEPRECATED_RUNTIME_ALGORITHM",
258        "Deprecated SAML runtime algorithm",
259        SsoErrorCategory::SuspectedAttack,
260    ),
261    descriptor(
262        "SAML_DESTINATION_MISMATCH",
263        "SAML destination mismatch",
264        SsoErrorCategory::SuspectedAttack,
265    ),
266    descriptor(
267        "SAML_ISSUER_MISMATCH",
268        "SAML issuer mismatch",
269        SsoErrorCategory::SuspectedAttack,
270    ),
271    descriptor(
272        "SAML_IN_RESPONSE_TO_MISMATCH",
273        "SAML InResponseTo mismatch",
274        SsoErrorCategory::SuspectedAttack,
275    ),
276    descriptor(
277        "SAML_TIMESTAMP_INVALID",
278        "SAML timestamp is invalid",
279        SsoErrorCategory::SuspectedAttack,
280    ),
281    descriptor(
282        "SAML_RECIPIENT_MISMATCH",
283        "SAML recipient mismatch",
284        SsoErrorCategory::SuspectedAttack,
285    ),
286    descriptor(
287        "INVALID_EMAIL_DOMAIN",
288        "Invalid SSO email domain",
289        SsoErrorCategory::SuspectedAttack,
290    ),
291    descriptor(
292        "SAML_SIGNATURE_VALIDATION_NOT_IMPLEMENTED",
293        "SAML signature validation is not enabled",
294        SsoErrorCategory::Unsupported,
295    ),
296    descriptor(
297        "ENCRYPTED_SAML_ASSERTION_UNSUPPORTED",
298        "Encrypted SAML assertion is not supported",
299        SsoErrorCategory::Unsupported,
300    ),
301    descriptor(
302        "SAML_AUTHN_REQUEST_SIGNING_NOT_SUPPORTED",
303        "SAML AuthnRequest signing is not enabled",
304        SsoErrorCategory::Unsupported,
305    ),
306    descriptor(
307        "SAML_AUTHN_REQUEST_SIGNING_FAILED",
308        "SAML AuthnRequest signing failed",
309        SsoErrorCategory::Unexpected,
310    ),
311];
312
313const fn descriptor(
314    code: &'static str,
315    message: &'static str,
316    category: SsoErrorCategory,
317) -> SsoErrorDescriptor {
318    SsoErrorDescriptor {
319        code,
320        message,
321        category,
322    }
323}
324
325pub fn plugin_error_codes() -> Vec<PluginErrorCode> {
326    sso_error_descriptors()
327        .iter()
328        .map(|descriptor| PluginErrorCode::new(descriptor.code, descriptor.message))
329        .collect()
330}
331
332/// Return all SSO error descriptors known by the plugin.
333pub fn sso_error_descriptors() -> &'static [SsoErrorDescriptor] {
334    ERROR_DESCRIPTORS
335}
336
337/// Look up the high-level category for a stable SSO error code.
338pub fn sso_error_category(code: &str) -> SsoErrorCategory {
339    sso_error_descriptors()
340        .iter()
341        .find(|descriptor| descriptor.code == code)
342        .map(|descriptor| descriptor.category)
343        .unwrap_or(SsoErrorCategory::Unexpected)
344}