1use std::{str::Utf8Error, sync::Arc};
18
19use headers::authorization::InvalidBearerToken;
20use http::{header::ToStrError, StatusCode};
21use mas_http::{catch_http_codes, form_urlencoded_request, json_request, json_response};
22use mas_jose::{
23 claims::ClaimError,
24 jwa::InvalidAlgorithm,
25 jwt::{JwtDecodeError, JwtSignatureError, NoKeyWorked},
26};
27use oauth2_types::{
28 errors::ClientErrorCode, oidc::ProviderMetadataVerificationError, pkce::CodeChallengeError,
29};
30use serde::{Deserialize, Serialize};
31use thiserror::Error;
32pub use tower::BoxError;
33
34#[derive(Debug, Error)]
36#[error(transparent)]
37pub enum Error {
38 Discovery(#[from] DiscoveryError),
40
41 Jwks(#[from] JwksError),
43
44 Registration(#[from] RegistrationError),
46
47 Authorization(#[from] AuthorizationError),
49
50 TokenAuthorizationCode(#[from] TokenAuthorizationCodeError),
52
53 TokenClientCredentials(#[from] TokenRequestError),
55
56 TokenRefresh(#[from] TokenRefreshError),
58
59 TokenRevoke(#[from] TokenRevokeError),
61
62 UserInfo(#[from] UserInfoError),
64
65 Introspection(#[from] IntrospectionError),
67
68 AccountManagement(#[from] AccountManagementError),
70}
71
72#[derive(Debug, Error)]
74pub enum DiscoveryError {
75 #[error(transparent)]
77 IntoUrl(#[from] url::ParseError),
78
79 #[error(transparent)]
81 IntoHttp(#[from] http::Error),
82
83 #[error(transparent)]
85 Http(#[from] HttpError),
86
87 #[error(transparent)]
89 FromJson(#[from] serde_json::Error),
90
91 #[error(transparent)]
93 Validation(#[from] ProviderMetadataVerificationError),
94
95 #[error(transparent)]
97 Service(BoxError),
98
99 #[error("Discovery is disabled for this provider")]
101 Disabled,
102}
103
104impl<S> From<json_response::Error<S>> for DiscoveryError
105where
106 S: Into<DiscoveryError>,
107{
108 fn from(err: json_response::Error<S>) -> Self {
109 match err {
110 json_response::Error::Deserialize { inner } => inner.into(),
111 json_response::Error::Service { inner } => inner.into(),
112 }
113 }
114}
115
116impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for DiscoveryError
117where
118 S: Into<BoxError>,
119{
120 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
121 match err {
122 catch_http_codes::Error::HttpError { status_code, inner } => {
123 Self::Http(HttpError::new(status_code, inner))
124 }
125 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
126 }
127 }
128}
129
130#[derive(Debug, Error)]
132pub enum RegistrationError {
133 #[error(transparent)]
135 IntoHttp(#[from] http::Error),
136
137 #[error(transparent)]
139 Json(#[from] serde_json::Error),
140
141 #[error(transparent)]
143 Http(#[from] HttpError),
144
145 #[error("missing client secret in response")]
148 MissingClientSecret,
149
150 #[error(transparent)]
152 Service(BoxError),
153}
154
155impl<S> From<json_request::Error<S>> for RegistrationError
156where
157 S: Into<RegistrationError>,
158{
159 fn from(err: json_request::Error<S>) -> Self {
160 match err {
161 json_request::Error::Serialize { inner } => inner.into(),
162 json_request::Error::Service { inner } => inner.into(),
163 }
164 }
165}
166
167impl<S> From<json_response::Error<S>> for RegistrationError
168where
169 S: Into<RegistrationError>,
170{
171 fn from(err: json_response::Error<S>) -> Self {
172 match err {
173 json_response::Error::Deserialize { inner } => inner.into(),
174 json_response::Error::Service { inner } => inner.into(),
175 }
176 }
177}
178
179impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for RegistrationError
180where
181 S: Into<BoxError>,
182{
183 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
184 match err {
185 catch_http_codes::Error::HttpError { status_code, inner } => {
186 HttpError::new(status_code, inner).into()
187 }
188 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
189 }
190 }
191}
192
193#[derive(Debug, Error)]
195pub enum PushedAuthorizationError {
196 #[error(transparent)]
198 UrlEncoded(#[from] serde_urlencoded::ser::Error),
199
200 #[error(transparent)]
202 IntoHttp(#[from] http::Error),
203
204 #[error(transparent)]
206 Credentials(#[from] CredentialsError),
207
208 #[error(transparent)]
210 Http(#[from] HttpError),
211
212 #[error(transparent)]
214 Json(#[from] serde_json::Error),
215
216 #[error(transparent)]
218 Service(BoxError),
219}
220
221impl<S> From<form_urlencoded_request::Error<S>> for PushedAuthorizationError
222where
223 S: Into<PushedAuthorizationError>,
224{
225 fn from(err: form_urlencoded_request::Error<S>) -> Self {
226 match err {
227 form_urlencoded_request::Error::Serialize { inner } => inner.into(),
228 form_urlencoded_request::Error::Service { inner } => inner.into(),
229 }
230 }
231}
232
233impl<S> From<json_response::Error<S>> for PushedAuthorizationError
234where
235 S: Into<PushedAuthorizationError>,
236{
237 fn from(err: json_response::Error<S>) -> Self {
238 match err {
239 json_response::Error::Deserialize { inner } => inner.into(),
240 json_response::Error::Service { inner } => inner.into(),
241 }
242 }
243}
244
245impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for PushedAuthorizationError
246where
247 S: Into<BoxError>,
248{
249 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
250 match err {
251 catch_http_codes::Error::HttpError { status_code, inner } => {
252 HttpError::new(status_code, inner).into()
253 }
254 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
255 }
256 }
257}
258
259#[derive(Debug, Error)]
261pub enum AuthorizationError {
262 #[error(transparent)]
264 Pkce(#[from] CodeChallengeError),
265
266 #[error(transparent)]
268 UrlEncoded(#[from] serde_urlencoded::ser::Error),
269
270 #[error(transparent)]
272 PushedAuthorization(#[from] PushedAuthorizationError),
273}
274
275#[derive(Debug, Error)]
277pub enum TokenRequestError {
278 #[error(transparent)]
280 IntoHttp(#[from] http::Error),
281
282 #[error(transparent)]
284 Credentials(#[from] CredentialsError),
285
286 #[error(transparent)]
288 UrlEncoded(#[from] serde_urlencoded::ser::Error),
289
290 #[error(transparent)]
292 Http(#[from] HttpError),
293
294 #[error(transparent)]
296 Json(#[from] serde_json::Error),
297
298 #[error(transparent)]
300 Service(BoxError),
301}
302
303impl<S> From<form_urlencoded_request::Error<S>> for TokenRequestError
304where
305 S: Into<TokenRequestError>,
306{
307 fn from(err: form_urlencoded_request::Error<S>) -> Self {
308 match err {
309 form_urlencoded_request::Error::Serialize { inner } => inner.into(),
310 form_urlencoded_request::Error::Service { inner } => inner.into(),
311 }
312 }
313}
314
315impl<S> From<json_response::Error<S>> for TokenRequestError
316where
317 S: Into<TokenRequestError>,
318{
319 fn from(err: json_response::Error<S>) -> Self {
320 match err {
321 json_response::Error::Deserialize { inner } => inner.into(),
322 json_response::Error::Service { inner } => inner.into(),
323 }
324 }
325}
326
327impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for TokenRequestError
328where
329 S: Into<BoxError>,
330{
331 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
332 match err {
333 catch_http_codes::Error::HttpError { status_code, inner } => {
334 HttpError::new(status_code, inner).into()
335 }
336 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
337 }
338 }
339}
340
341#[derive(Debug, Error)]
343pub enum TokenAuthorizationCodeError {
344 #[error(transparent)]
346 Token(#[from] TokenRequestError),
347
348 #[error(transparent)]
350 IdToken(#[from] IdTokenError),
351}
352
353#[derive(Debug, Error)]
355pub enum TokenRefreshError {
356 #[error(transparent)]
358 Token(#[from] TokenRequestError),
359
360 #[error(transparent)]
362 IdToken(#[from] IdTokenError),
363}
364
365#[derive(Debug, Error)]
367pub enum TokenRevokeError {
368 #[error(transparent)]
370 IntoHttp(#[from] http::Error),
371
372 #[error(transparent)]
374 Credentials(#[from] CredentialsError),
375
376 #[error(transparent)]
378 UrlEncoded(#[from] serde_urlencoded::ser::Error),
379
380 #[error(transparent)]
382 Json(#[from] serde_json::Error),
383
384 #[error(transparent)]
386 Http(#[from] HttpError),
387
388 #[error(transparent)]
390 Service(BoxError),
391}
392
393impl<S> From<form_urlencoded_request::Error<S>> for TokenRevokeError
394where
395 S: Into<TokenRevokeError>,
396{
397 fn from(err: form_urlencoded_request::Error<S>) -> Self {
398 match err {
399 form_urlencoded_request::Error::Serialize { inner } => inner.into(),
400 form_urlencoded_request::Error::Service { inner } => inner.into(),
401 }
402 }
403}
404
405impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for TokenRevokeError
406where
407 S: Into<BoxError>,
408{
409 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
410 match err {
411 catch_http_codes::Error::HttpError { status_code, inner } => {
412 HttpError::new(status_code, inner).into()
413 }
414 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
415 }
416 }
417}
418
419#[derive(Debug, Error)]
421pub enum UserInfoError {
422 #[error(transparent)]
424 Discovery(#[from] Arc<DiscoveryError>),
425
426 #[error("missing UserInfo support")]
428 MissingUserInfoSupport,
429
430 #[error("missing token")]
432 MissingToken,
433
434 #[error("missing client metadata")]
436 MissingClientMetadata,
437
438 #[error(transparent)]
440 Token(#[from] InvalidBearerToken),
441
442 #[error(transparent)]
444 IntoHttp(#[from] http::Error),
445
446 #[error("missing response content-type")]
448 MissingResponseContentType,
449
450 #[error("could not decoded response content-type: {0}")]
452 DecodeResponseContentType(#[from] ToStrError),
453
454 #[error("invalid response content-type")]
456 InvalidResponseContentTypeValue,
457
458 #[error("unexpected response content-type {got:?}, expected {expected:?}")]
460 UnexpectedResponseContentType {
461 expected: String,
463 got: String,
465 },
466
467 #[error(transparent)]
469 FromUtf8(#[from] Utf8Error),
470
471 #[error(transparent)]
473 Json(#[from] serde_json::Error),
474
475 #[error(transparent)]
477 IdToken(#[from] IdTokenError),
478
479 #[error(transparent)]
481 Http(#[from] HttpError),
482
483 #[error(transparent)]
485 Service(BoxError),
486}
487
488impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for UserInfoError
489where
490 S: Into<BoxError>,
491{
492 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
493 match err {
494 catch_http_codes::Error::HttpError { status_code, inner } => {
495 HttpError::new(status_code, inner).into()
496 }
497 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
498 }
499 }
500}
501
502#[derive(Debug, Error)]
504pub enum IntrospectionError {
505 #[error(transparent)]
507 IntoHttp(#[from] http::Error),
508
509 #[error(transparent)]
511 Credentials(#[from] CredentialsError),
512
513 #[error(transparent)]
515 Token(#[from] InvalidBearerToken),
516
517 #[error(transparent)]
519 UrlEncoded(#[from] serde_urlencoded::ser::Error),
520
521 #[error(transparent)]
523 Json(#[from] serde_json::Error),
524
525 #[error(transparent)]
527 Http(#[from] HttpError),
528
529 #[error(transparent)]
531 Service(BoxError),
532}
533
534impl<S> From<form_urlencoded_request::Error<S>> for IntrospectionError
535where
536 S: Into<IntrospectionError>,
537{
538 fn from(err: form_urlencoded_request::Error<S>) -> Self {
539 match err {
540 form_urlencoded_request::Error::Serialize { inner } => inner.into(),
541 form_urlencoded_request::Error::Service { inner } => inner.into(),
542 }
543 }
544}
545
546impl<S> From<json_response::Error<S>> for IntrospectionError
547where
548 S: Into<IntrospectionError>,
549{
550 fn from(err: json_response::Error<S>) -> Self {
551 match err {
552 json_response::Error::Deserialize { inner } => inner.into(),
553 json_response::Error::Service { inner } => inner.into(),
554 }
555 }
556}
557
558impl<S> From<catch_http_codes::Error<S, Option<ErrorBody>>> for IntrospectionError
559where
560 S: Into<BoxError>,
561{
562 fn from(err: catch_http_codes::Error<S, Option<ErrorBody>>) -> Self {
563 match err {
564 catch_http_codes::Error::HttpError { status_code, inner } => {
565 HttpError::new(status_code, inner).into()
566 }
567 catch_http_codes::Error::Service { inner } => Self::Service(inner.into()),
568 }
569 }
570}
571
572#[derive(Debug, Error)]
574pub enum JwksError {
575 #[error(transparent)]
577 IntoHttp(#[from] http::Error),
578
579 #[error(transparent)]
581 Json(#[from] serde_json::Error),
582
583 #[error(transparent)]
585 Service(BoxError),
586}
587
588impl<S> From<json_response::Error<S>> for JwksError
589where
590 S: Into<BoxError>,
591{
592 fn from(err: json_response::Error<S>) -> Self {
593 match err {
594 json_response::Error::Service { inner } => Self::Service(inner.into()),
595 json_response::Error::Deserialize { inner } => Self::Json(inner),
596 }
597 }
598}
599
600#[derive(Debug, Error)]
602pub enum JwtVerificationError {
603 #[error(transparent)]
605 JwtDecode(#[from] JwtDecodeError),
606
607 #[error(transparent)]
609 JwtSignature(#[from] NoKeyWorked),
610
611 #[error(transparent)]
613 Claim(#[from] ClaimError),
614
615 #[error("wrong signature alg")]
618 WrongSignatureAlg,
619}
620
621#[derive(Debug, Error)]
623pub enum IdTokenError {
624 #[error("ID token is missing")]
626 MissingIdToken,
627
628 #[error("Authorization ID token is missing")]
631 MissingAuthIdToken,
632
633 #[error(transparent)]
635 Jwt(#[from] JwtVerificationError),
636
637 #[error(transparent)]
639 Claim(#[from] ClaimError),
640
641 #[error("wrong subject identifier")]
644 WrongSubjectIdentifier,
645
646 #[error("wrong authentication time")]
649 WrongAuthTime,
650}
651
652#[derive(Debug, Clone, Error)]
654#[error("{status}: {body:?}")]
655pub struct HttpError {
656 pub status: StatusCode,
658
659 pub body: Option<ErrorBody>,
661}
662
663impl HttpError {
664 #[must_use]
666 pub fn new(status: StatusCode, body: Option<ErrorBody>) -> Self {
667 Self { status, body }
668 }
669}
670
671#[derive(Debug, Clone, Serialize, Deserialize)]
673pub struct ErrorBody {
674 pub error: ClientErrorCode,
676
677 pub error_description: Option<String>,
679}
680
681#[derive(Debug, Error)]
683pub enum CredentialsError {
684 #[error("unsupported authentication method")]
686 UnsupportedMethod,
687
688 #[error("no private key was found for the given algorithm")]
691 NoPrivateKeyFound,
692
693 #[error("invalid algorithm: {0}")]
695 InvalidSigningAlgorithm(#[from] InvalidAlgorithm),
696
697 #[error(transparent)]
699 JwtClaims(#[from] ClaimError),
700
701 #[error("Wrong algorithm for key")]
703 JwtWrongAlgorithm,
704
705 #[error(transparent)]
707 JwtSignature(#[from] JwtSignatureError),
708
709 #[error(transparent)]
711 Custom(BoxError),
712}
713
714#[derive(Debug, Error)]
716pub enum AccountManagementError {
717 #[error(transparent)]
719 UrlEncoded(#[from] serde_urlencoded::ser::Error),
720}