oauth2_types/
errors.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7//! Error types returned by an authorization server.
8
9use std::borrow::Cow;
10
11use serde::{Deserialize, Serialize};
12use serde_with::{DeserializeFromStr, SerializeDisplay};
13
14/// A client error returned by an authorization server.
15///
16/// To construct this with a default description for the error code, use its
17/// `From<ClientErrorCode>` implementation.
18#[derive(Debug, Serialize, Deserialize, Clone)]
19pub struct ClientError {
20    /// The error code.
21    pub error: ClientErrorCode,
22
23    /// A human-readable description of the error.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub error_description: Option<Cow<'static, str>>,
26}
27
28impl ClientError {
29    /// Creates a new `ClientError` with the given error code and description.
30    #[must_use]
31    pub const fn new(error: ClientErrorCode, error_description: &'static str) -> Self {
32        Self {
33            error,
34            error_description: Some(Cow::Borrowed(error_description)),
35        }
36    }
37
38    /// Changes the description of this `ClientError` with the given `String`.
39    #[must_use]
40    pub fn with_description(mut self, description: String) -> Self {
41        self.error_description = Some(Cow::Owned(description));
42        self
43    }
44}
45
46impl From<ClientErrorCode> for ClientError {
47    fn from(error: ClientErrorCode) -> Self {
48        let desc = error.default_description();
49        Self::new(error, desc)
50    }
51}
52
53/// Client error codes defined in OAuth2.0, OpenID Connect and their extensions.
54#[derive(Debug, Clone, PartialEq, Eq, SerializeDisplay, DeserializeFromStr)]
55pub enum ClientErrorCode {
56    /// `invalid_request`
57    ///
58    /// The request is missing a required parameter, includes an invalid
59    /// parameter value, includes a parameter more than once, or is otherwise
60    /// malformed.
61    ///
62    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
63    InvalidRequest,
64
65    /// `invalid_client`
66    ///
67    /// Client authentication failed (e.g., unknown client, no client
68    /// authentication included, or unsupported authentication method).
69    ///
70    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
71    InvalidClient,
72
73    /// `invalid_grant`
74    ///
75    /// The provided authorization grant (e.g., authorization code, resource
76    /// owner credentials) or refresh token is invalid, expired, revoked, does
77    /// not match the redirection URI used in the authorization request, or was
78    /// issued to another client.
79    ///
80    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
81    InvalidGrant,
82
83    /// `unauthorized_client`
84    ///
85    /// The authenticated client is not authorized to use this authorization
86    /// grant type.
87    ///
88    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
89    UnauthorizedClient,
90
91    /// `unsupported_grant_type`
92    ///
93    /// The authorization grant type is not supported by the authorization
94    /// server.
95    ///
96    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
97    UnsupportedGrantType,
98
99    /// `access_denied`
100    ///
101    /// The resource owner or authorization server denied the request.
102    ///
103    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
104    AccessDenied,
105
106    /// `unsupported_response_type`
107    ///
108    /// The authorization server does not support obtaining an authorization
109    /// code using this method.
110    ///
111    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
112    UnsupportedResponseType,
113
114    /// `invalid_scope`
115    ///
116    /// The requested scope is invalid, unknown, malformed, or exceeds the scope
117    /// granted by the resource owner.
118    ///
119    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
120    InvalidScope,
121
122    /// `server_error`
123    ///
124    /// The authorization server encountered an unexpected condition that
125    /// prevented it from fulfilling the request.
126    ///
127    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
128    ServerError,
129
130    /// `temporarily_unavailable`
131    ///
132    /// The authorization server is currently unable to handle the request due
133    /// to a temporary overloading or maintenance of the server.
134    ///
135    /// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
136    TemporarilyUnavailable,
137
138    /// `interaction_required`
139    ///
140    /// The authorization server requires end-user interaction of some form to
141    /// proceed.
142    ///
143    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
144    InteractionRequired,
145
146    /// `login_required`
147    ///
148    /// The authorization server requires end-user authentication.
149    ///
150    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
151    LoginRequired,
152
153    /// `account_selection_required`
154    ///
155    /// The end-user is required to select a session at the authorization
156    /// server.
157    ///
158    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
159    AccountSelectionRequired,
160
161    /// `consent_required`
162    ///
163    /// The authorization server requires end-user consent.
164    ///
165    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
166    ConsentRequired,
167
168    /// `invalid_request_uri`
169    ///
170    /// The `request_uri` in the authorization request returns an error or
171    /// contains invalid data.
172    ///
173    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
174    InvalidRequestUri,
175
176    /// `invalid_request_object`
177    ///
178    /// The request parameter contains an invalid request object.
179    ///
180    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
181    InvalidRequestObject,
182
183    /// `request_not_supported`
184    ///
185    /// The authorization server does not support use of the `request`
186    /// parameter.
187    ///
188    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
189    RequestNotSupported,
190
191    /// `request_uri_not_supported`
192    ///
193    /// The authorization server does not support use of the `request_uri`
194    /// parameter.
195    ///
196    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
197    RequestUriNotSupported,
198
199    /// `registration_not_supported`
200    ///
201    /// The authorization server does not support use of the `registration`
202    /// parameter.
203    ///
204    /// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
205    RegistrationNotSupported,
206
207    /// `invalid_redirect_uri`
208    ///
209    /// The value of one or more redirection URIs is invalid.
210    ///
211    /// From [RFC7591](https://www.rfc-editor.org/rfc/rfc7591#section-3.2.2).
212    InvalidRedirectUri,
213
214    /// `invalid_client_metadata`
215    ///
216    /// The value of one of the client metadata fields is invalid and the server
217    /// has rejected this request.
218    ///
219    /// From [RFC7591](https://www.rfc-editor.org/rfc/rfc7591#section-3.2.2).
220    InvalidClientMetadata,
221
222    /// `authorization_pending`
223    ///
224    /// The authorization request is still pending as the end user hasn't yet
225    /// completed the user-interaction steps.
226    ///
227    /// The client should repeat the access token request to the token endpoint
228    /// (a process known as polling).  Before each new request, the client
229    /// must wait at least the number of seconds specified by the `interval`
230    /// parameter of the device authorization response, or 5 seconds if none was
231    /// provided, and respect any increase in the polling interval required
232    /// by the [`ClientErrorCode::SlowDown`] error.
233    ///
234    /// From [RFC8628](https://www.rfc-editor.org/rfc/rfc8628#section-3.5).
235    AuthorizationPending,
236
237    /// `slow_down`
238    ///
239    /// A variant of [`ClientErrorCode::AuthorizationPending`], the
240    /// authorization request is still pending and polling should continue,
241    /// but the interval must be increased by 5 seconds for this and all
242    /// subsequent requests.
243    ///
244    /// From [RFC8628](https://www.rfc-editor.org/rfc/rfc8628#section-3.5).
245    SlowDown,
246
247    /// `expired_token`
248    ///
249    /// The `device_code` has expired, and the device authorization session has
250    /// concluded.
251    ///
252    /// The client may commence a new device authorization request but should
253    /// wait for user interaction before restarting to avoid unnecessary
254    /// polling.
255    ///
256    /// From [RFC8628](https://www.rfc-editor.org/rfc/rfc8628#section-3.5).
257    ExpiredToken,
258
259    /// `unsupported_token_type`
260    ///
261    /// The authorization server does not support the revocation of the
262    /// presented token type.  That is, the client tried to revoke an access
263    /// token on a server not supporting this feature.
264    ///
265    /// From [RFC7009](https://www.rfc-editor.org/rfc/rfc7009#section-2.2.1).
266    UnsupportedTokenType,
267
268    /// Another error code.
269    Unknown(String),
270}
271
272impl core::fmt::Display for ClientErrorCode {
273    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
274        match self {
275            ClientErrorCode::InvalidRequest => f.write_str("invalid_request"),
276            ClientErrorCode::InvalidClient => f.write_str("invalid_client"),
277            ClientErrorCode::InvalidGrant => f.write_str("invalid_grant"),
278            ClientErrorCode::UnauthorizedClient => f.write_str("unauthorized_client"),
279            ClientErrorCode::UnsupportedGrantType => f.write_str("unsupported_grant_type"),
280            ClientErrorCode::AccessDenied => f.write_str("access_denied"),
281            ClientErrorCode::UnsupportedResponseType => f.write_str("unsupported_response_type"),
282            ClientErrorCode::InvalidScope => f.write_str("invalid_scope"),
283            ClientErrorCode::ServerError => f.write_str("server_error"),
284            ClientErrorCode::TemporarilyUnavailable => f.write_str("temporarily_unavailable"),
285            ClientErrorCode::InteractionRequired => f.write_str("interaction_required"),
286            ClientErrorCode::LoginRequired => f.write_str("login_required"),
287            ClientErrorCode::AccountSelectionRequired => f.write_str("account_selection_required"),
288            ClientErrorCode::ConsentRequired => f.write_str("consent_required"),
289            ClientErrorCode::InvalidRequestUri => f.write_str("invalid_request_uri"),
290            ClientErrorCode::InvalidRequestObject => f.write_str("invalid_request_object"),
291            ClientErrorCode::RequestNotSupported => f.write_str("request_not_supported"),
292            ClientErrorCode::RequestUriNotSupported => f.write_str("request_uri_not_supported"),
293            ClientErrorCode::RegistrationNotSupported => f.write_str("registration_not_supported"),
294            ClientErrorCode::InvalidRedirectUri => f.write_str("invalid_redirect_uri"),
295            ClientErrorCode::InvalidClientMetadata => f.write_str("invalid_client_metadata"),
296            ClientErrorCode::AuthorizationPending => f.write_str("authorization_pending"),
297            ClientErrorCode::SlowDown => f.write_str("slow_down"),
298            ClientErrorCode::ExpiredToken => f.write_str("expired_token"),
299            ClientErrorCode::UnsupportedTokenType => f.write_str("unsupported_token_type"),
300            ClientErrorCode::Unknown(value) => f.write_str(value),
301        }
302    }
303}
304
305impl core::str::FromStr for ClientErrorCode {
306    type Err = core::convert::Infallible;
307
308    fn from_str(s: &str) -> Result<Self, Self::Err> {
309        match s {
310            "invalid_request" => Ok(ClientErrorCode::InvalidRequest),
311            "invalid_client" => Ok(ClientErrorCode::InvalidClient),
312            "invalid_grant" => Ok(ClientErrorCode::InvalidGrant),
313            "unauthorized_client" => Ok(ClientErrorCode::UnauthorizedClient),
314            "unsupported_grant_type" => Ok(ClientErrorCode::UnsupportedGrantType),
315            "access_denied" => Ok(ClientErrorCode::AccessDenied),
316            "unsupported_response_type" => Ok(ClientErrorCode::UnsupportedResponseType),
317            "invalid_scope" => Ok(ClientErrorCode::InvalidScope),
318            "server_error" => Ok(ClientErrorCode::ServerError),
319            "temporarily_unavailable" => Ok(ClientErrorCode::TemporarilyUnavailable),
320            "interaction_required" => Ok(ClientErrorCode::InteractionRequired),
321            "login_required" => Ok(ClientErrorCode::LoginRequired),
322            "account_selection_required" => Ok(ClientErrorCode::AccountSelectionRequired),
323            "consent_required" => Ok(ClientErrorCode::ConsentRequired),
324            "invalid_request_uri" => Ok(ClientErrorCode::InvalidRequestUri),
325            "invalid_request_object" => Ok(ClientErrorCode::InvalidRequestObject),
326            "request_not_supported" => Ok(ClientErrorCode::RequestNotSupported),
327            "request_uri_not_supported" => Ok(ClientErrorCode::RequestUriNotSupported),
328            "registration_not_supported" => Ok(ClientErrorCode::RegistrationNotSupported),
329            "invalid_redirect_uri" => Ok(ClientErrorCode::InvalidRedirectUri),
330            "invalid_client_metadata" => Ok(ClientErrorCode::InvalidClientMetadata),
331            "authorization_pending" => Ok(ClientErrorCode::AuthorizationPending),
332            "slow_down" => Ok(ClientErrorCode::SlowDown),
333            "expired_token" => Ok(ClientErrorCode::ExpiredToken),
334            "unsupported_token_type" => Ok(ClientErrorCode::UnsupportedTokenType),
335            _ => Ok(ClientErrorCode::Unknown(s.to_owned())),
336        }
337    }
338}
339
340impl ClientErrorCode {
341    /// Get the default description for this `ClientErrorCode`.
342    ///
343    /// Note that [`ClientErrorCode::Unknown`] returns an empty string.
344    #[must_use]
345    pub fn default_description(&self) -> &'static str {
346        match self {
347            ClientErrorCode::InvalidRequest => {
348                "The request is missing a required parameter, includes an \
349                invalid parameter value, includes a parameter more than once, \
350                or is otherwise malformed."
351            }
352            ClientErrorCode::InvalidClient => "Client authentication failed.",
353            ClientErrorCode::InvalidGrant => {
354                "The provided access grant is invalid, expired, or revoked."
355            }
356            ClientErrorCode::UnauthorizedClient => {
357                "The client is not authorized to request an access token using this method."
358            }
359            ClientErrorCode::UnsupportedGrantType => {
360                "The authorization grant type is not supported by the authorization server."
361            }
362            ClientErrorCode::AccessDenied => {
363                "The resource owner or authorization server denied the request."
364            }
365            ClientErrorCode::UnsupportedResponseType => {
366                "The authorization server does not support obtaining an access \
367                token using this method."
368            }
369            ClientErrorCode::InvalidScope => {
370                "The requested scope is invalid, unknown, or malformed."
371            }
372            ClientErrorCode::ServerError => {
373                "The authorization server encountered an unexpected condition \
374                that prevented it from fulfilling the request."
375            }
376            ClientErrorCode::TemporarilyUnavailable => {
377                "The authorization server is currently unable to handle the request \
378                due to a temporary overloading or maintenance of the server."
379            }
380            ClientErrorCode::InteractionRequired => {
381                "The Authorization Server requires End-User interaction of some form to proceed."
382            }
383            ClientErrorCode::LoginRequired => {
384                "The Authorization Server requires End-User authentication."
385            }
386            ClientErrorCode::AccountSelectionRequired => {
387                "The End-User is required to select a session at the Authorization Server."
388            }
389            ClientErrorCode::ConsentRequired => {
390                "The Authorization Server requires End-User consent."
391            }
392            ClientErrorCode::InvalidRequestUri => {
393                "The request_uri in the Authorization Request returns an error \
394                or contains invalid data."
395            }
396            ClientErrorCode::InvalidRequestObject => {
397                "The request parameter contains an invalid Request Object."
398            }
399            ClientErrorCode::RequestNotSupported => {
400                "The provider does not support use of the request parameter."
401            }
402            ClientErrorCode::RequestUriNotSupported => {
403                "The provider does not support use of the request_uri parameter."
404            }
405            ClientErrorCode::RegistrationNotSupported => {
406                "The provider does not support use of the registration parameter."
407            }
408            ClientErrorCode::InvalidRedirectUri => {
409                "The value of one or more redirection URIs is invalid."
410            }
411            ClientErrorCode::InvalidClientMetadata => {
412                "The value of one of the client metadata fields is invalid"
413            }
414            ClientErrorCode::AuthorizationPending => "The authorization request is still pending",
415            ClientErrorCode::SlowDown => {
416                "The interval must be increased by 5 seconds for this and all subsequent requests"
417            }
418            ClientErrorCode::ExpiredToken => {
419                "The \"device_code\" has expired, and the device authorization session has concluded"
420            }
421            ClientErrorCode::UnsupportedTokenType => {
422                "The authorization server does not support the revocation of the presented token type."
423            }
424            ClientErrorCode::Unknown(_) => "",
425        }
426    }
427}
428
429#[cfg(test)]
430mod tests {
431    use super::*;
432
433    #[test]
434    fn serialize_client_error_code() {
435        assert_eq!(
436            serde_json::to_string(&ClientErrorCode::InvalidRequest).unwrap(),
437            "\"invalid_request\""
438        );
439        assert_eq!(
440            serde_json::to_string(&ClientErrorCode::InvalidClient).unwrap(),
441            "\"invalid_client\""
442        );
443        assert_eq!(
444            serde_json::to_string(&ClientErrorCode::InvalidGrant).unwrap(),
445            "\"invalid_grant\""
446        );
447        assert_eq!(
448            serde_json::to_string(&ClientErrorCode::UnauthorizedClient).unwrap(),
449            "\"unauthorized_client\""
450        );
451        assert_eq!(
452            serde_json::to_string(&ClientErrorCode::UnsupportedGrantType).unwrap(),
453            "\"unsupported_grant_type\""
454        );
455        assert_eq!(
456            serde_json::to_string(&ClientErrorCode::AccessDenied).unwrap(),
457            "\"access_denied\""
458        );
459        assert_eq!(
460            serde_json::to_string(&ClientErrorCode::UnsupportedResponseType).unwrap(),
461            "\"unsupported_response_type\""
462        );
463        assert_eq!(
464            serde_json::to_string(&ClientErrorCode::InvalidScope).unwrap(),
465            "\"invalid_scope\""
466        );
467        assert_eq!(
468            serde_json::to_string(&ClientErrorCode::ServerError).unwrap(),
469            "\"server_error\""
470        );
471        assert_eq!(
472            serde_json::to_string(&ClientErrorCode::TemporarilyUnavailable).unwrap(),
473            "\"temporarily_unavailable\""
474        );
475        assert_eq!(
476            serde_json::to_string(&ClientErrorCode::InteractionRequired).unwrap(),
477            "\"interaction_required\""
478        );
479        assert_eq!(
480            serde_json::to_string(&ClientErrorCode::LoginRequired).unwrap(),
481            "\"login_required\""
482        );
483        assert_eq!(
484            serde_json::to_string(&ClientErrorCode::AccountSelectionRequired).unwrap(),
485            "\"account_selection_required\""
486        );
487        assert_eq!(
488            serde_json::to_string(&ClientErrorCode::ConsentRequired).unwrap(),
489            "\"consent_required\""
490        );
491        assert_eq!(
492            serde_json::to_string(&ClientErrorCode::InvalidRequestUri).unwrap(),
493            "\"invalid_request_uri\""
494        );
495        assert_eq!(
496            serde_json::to_string(&ClientErrorCode::InvalidRequestObject).unwrap(),
497            "\"invalid_request_object\""
498        );
499        assert_eq!(
500            serde_json::to_string(&ClientErrorCode::RequestNotSupported).unwrap(),
501            "\"request_not_supported\""
502        );
503        assert_eq!(
504            serde_json::to_string(&ClientErrorCode::RequestUriNotSupported).unwrap(),
505            "\"request_uri_not_supported\""
506        );
507        assert_eq!(
508            serde_json::to_string(&ClientErrorCode::RegistrationNotSupported).unwrap(),
509            "\"registration_not_supported\""
510        );
511        assert_eq!(
512            serde_json::to_string(&ClientErrorCode::InvalidRedirectUri).unwrap(),
513            "\"invalid_redirect_uri\""
514        );
515        assert_eq!(
516            serde_json::to_string(&ClientErrorCode::InvalidClientMetadata).unwrap(),
517            "\"invalid_client_metadata\""
518        );
519
520        assert_eq!(
521            serde_json::to_string(&ClientErrorCode::Unknown("unknown_error_code".to_owned()))
522                .unwrap(),
523            "\"unknown_error_code\""
524        );
525    }
526
527    #[test]
528    fn deserialize_client_error_code() {
529        assert_eq!(
530            serde_json::from_str::<ClientErrorCode>("\"invalid_request\"").unwrap(),
531            ClientErrorCode::InvalidRequest
532        );
533        assert_eq!(
534            serde_json::from_str::<ClientErrorCode>("\"invalid_client\"").unwrap(),
535            ClientErrorCode::InvalidClient
536        );
537        assert_eq!(
538            serde_json::from_str::<ClientErrorCode>("\"invalid_grant\"").unwrap(),
539            ClientErrorCode::InvalidGrant
540        );
541        assert_eq!(
542            serde_json::from_str::<ClientErrorCode>("\"unauthorized_client\"").unwrap(),
543            ClientErrorCode::UnauthorizedClient
544        );
545        assert_eq!(
546            serde_json::from_str::<ClientErrorCode>("\"unsupported_grant_type\"").unwrap(),
547            ClientErrorCode::UnsupportedGrantType
548        );
549        assert_eq!(
550            serde_json::from_str::<ClientErrorCode>("\"access_denied\"").unwrap(),
551            ClientErrorCode::AccessDenied
552        );
553        assert_eq!(
554            serde_json::from_str::<ClientErrorCode>("\"unsupported_response_type\"").unwrap(),
555            ClientErrorCode::UnsupportedResponseType
556        );
557        assert_eq!(
558            serde_json::from_str::<ClientErrorCode>("\"invalid_scope\"").unwrap(),
559            ClientErrorCode::InvalidScope
560        );
561        assert_eq!(
562            serde_json::from_str::<ClientErrorCode>("\"server_error\"").unwrap(),
563            ClientErrorCode::ServerError
564        );
565        assert_eq!(
566            serde_json::from_str::<ClientErrorCode>("\"temporarily_unavailable\"").unwrap(),
567            ClientErrorCode::TemporarilyUnavailable
568        );
569        assert_eq!(
570            serde_json::from_str::<ClientErrorCode>("\"interaction_required\"").unwrap(),
571            ClientErrorCode::InteractionRequired
572        );
573        assert_eq!(
574            serde_json::from_str::<ClientErrorCode>("\"login_required\"").unwrap(),
575            ClientErrorCode::LoginRequired
576        );
577        assert_eq!(
578            serde_json::from_str::<ClientErrorCode>("\"account_selection_required\"").unwrap(),
579            ClientErrorCode::AccountSelectionRequired
580        );
581        assert_eq!(
582            serde_json::from_str::<ClientErrorCode>("\"consent_required\"").unwrap(),
583            ClientErrorCode::ConsentRequired
584        );
585        assert_eq!(
586            serde_json::from_str::<ClientErrorCode>("\"invalid_request_uri\"").unwrap(),
587            ClientErrorCode::InvalidRequestUri
588        );
589        assert_eq!(
590            serde_json::from_str::<ClientErrorCode>("\"invalid_request_object\"").unwrap(),
591            ClientErrorCode::InvalidRequestObject
592        );
593        assert_eq!(
594            serde_json::from_str::<ClientErrorCode>("\"request_not_supported\"").unwrap(),
595            ClientErrorCode::RequestNotSupported
596        );
597        assert_eq!(
598            serde_json::from_str::<ClientErrorCode>("\"request_uri_not_supported\"").unwrap(),
599            ClientErrorCode::RequestUriNotSupported
600        );
601        assert_eq!(
602            serde_json::from_str::<ClientErrorCode>("\"registration_not_supported\"").unwrap(),
603            ClientErrorCode::RegistrationNotSupported
604        );
605        assert_eq!(
606            serde_json::from_str::<ClientErrorCode>("\"invalid_redirect_uri\"").unwrap(),
607            ClientErrorCode::InvalidRedirectUri
608        );
609        assert_eq!(
610            serde_json::from_str::<ClientErrorCode>("\"invalid_client_metadata\"").unwrap(),
611            ClientErrorCode::InvalidClientMetadata
612        );
613
614        assert_eq!(
615            serde_json::from_str::<ClientErrorCode>("\"unknown_error_code\"").unwrap(),
616            ClientErrorCode::Unknown("unknown_error_code".to_owned())
617        );
618    }
619}