1use std::{fmt, ops::Deref};
12
13use language_tags::LanguageTag;
14use mas_iana::{
15    jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg},
16    oauth::{OAuthAccessTokenType, OAuthClientAuthenticationMethod, PkceCodeChallengeMethod},
17};
18use serde::{Deserialize, Serialize};
19use serde_with::{
20    DeserializeFromStr, SerializeDisplay, StringWithSeparator, formats::SpaceSeparator, serde_as,
21    skip_serializing_none,
22};
23use thiserror::Error;
24use url::Url;
25
26use crate::{
27    requests::{Display, GrantType, Prompt, ResponseMode},
28    response_type::ResponseType,
29};
30
31#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
34pub enum AuthenticationMethodOrAccessTokenType {
35    AuthenticationMethod(OAuthClientAuthenticationMethod),
37
38    AccessTokenType(OAuthAccessTokenType),
40
41    Unknown(String),
47}
48
49impl core::fmt::Display for AuthenticationMethodOrAccessTokenType {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        match self {
52            Self::AuthenticationMethod(m) => m.fmt(f),
53            Self::AccessTokenType(t) => t.fmt(f),
54            Self::Unknown(s) => s.fmt(f),
55        }
56    }
57}
58
59impl core::str::FromStr for AuthenticationMethodOrAccessTokenType {
60    type Err = core::convert::Infallible;
61
62    fn from_str(s: &str) -> Result<Self, Self::Err> {
63        match OAuthClientAuthenticationMethod::from_str(s) {
64            Ok(OAuthClientAuthenticationMethod::Unknown(_)) | Err(_) => {}
65            Ok(m) => return Ok(m.into()),
66        }
67
68        match OAuthAccessTokenType::from_str(s) {
69            Ok(OAuthAccessTokenType::Unknown(_)) | Err(_) => {}
70            Ok(m) => return Ok(m.into()),
71        }
72
73        Ok(Self::Unknown(s.to_owned()))
74    }
75}
76
77impl AuthenticationMethodOrAccessTokenType {
78    #[must_use]
81    pub fn authentication_method(&self) -> Option<&OAuthClientAuthenticationMethod> {
82        match self {
83            Self::AuthenticationMethod(m) => Some(m),
84            _ => None,
85        }
86    }
87
88    #[must_use]
91    pub fn access_token_type(&self) -> Option<&OAuthAccessTokenType> {
92        match self {
93            Self::AccessTokenType(t) => Some(t),
94            _ => None,
95        }
96    }
97}
98
99impl From<OAuthClientAuthenticationMethod> for AuthenticationMethodOrAccessTokenType {
100    fn from(t: OAuthClientAuthenticationMethod) -> Self {
101        Self::AuthenticationMethod(t)
102    }
103}
104
105impl From<OAuthAccessTokenType> for AuthenticationMethodOrAccessTokenType {
106    fn from(t: OAuthAccessTokenType) -> Self {
107        Self::AccessTokenType(t)
108    }
109}
110
111#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
113pub enum ApplicationType {
114    Web,
116
117    Native,
119
120    Unknown(String),
122}
123
124impl core::fmt::Display for ApplicationType {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        match self {
127            Self::Web => f.write_str("web"),
128            Self::Native => f.write_str("native"),
129            Self::Unknown(s) => f.write_str(s),
130        }
131    }
132}
133
134impl core::str::FromStr for ApplicationType {
135    type Err = core::convert::Infallible;
136
137    fn from_str(s: &str) -> Result<Self, Self::Err> {
138        match s {
139            "web" => Ok(Self::Web),
140            "native" => Ok(Self::Native),
141            s => Ok(Self::Unknown(s.to_owned())),
142        }
143    }
144}
145
146#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
152pub enum SubjectType {
153    Public,
155
156    Pairwise,
160
161    Unknown(String),
163}
164
165impl core::fmt::Display for SubjectType {
166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167        match self {
168            Self::Public => f.write_str("public"),
169            Self::Pairwise => f.write_str("pairwise"),
170            Self::Unknown(s) => f.write_str(s),
171        }
172    }
173}
174
175impl core::str::FromStr for SubjectType {
176    type Err = core::convert::Infallible;
177
178    fn from_str(s: &str) -> Result<Self, Self::Err> {
179        match s {
180            "public" => Ok(Self::Public),
181            "pairwise" => Ok(Self::Pairwise),
182            s => Ok(Self::Unknown(s.to_owned())),
183        }
184    }
185}
186
187#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
189pub enum ClaimType {
190    Normal,
192
193    Aggregated,
196
197    Distributed,
200
201    Unknown(String),
203}
204
205impl core::fmt::Display for ClaimType {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        match self {
208            Self::Normal => f.write_str("normal"),
209            Self::Aggregated => f.write_str("aggregated"),
210            Self::Distributed => f.write_str("distributed"),
211            Self::Unknown(s) => f.write_str(s),
212        }
213    }
214}
215
216impl core::str::FromStr for ClaimType {
217    type Err = core::convert::Infallible;
218
219    fn from_str(s: &str) -> Result<Self, Self::Err> {
220        match s {
221            "normal" => Ok(Self::Normal),
222            "aggregated" => Ok(Self::Aggregated),
223            "distributed" => Ok(Self::Distributed),
224            s => Ok(Self::Unknown(s.to_owned())),
225        }
226    }
227}
228
229#[derive(
233    SerializeDisplay, DeserializeFromStr, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
234)]
235#[non_exhaustive]
236pub enum AccountManagementAction {
237    Profile,
241
242    SessionsList,
246
247    SessionView,
251
252    SessionEnd,
256
257    AccountDeactivate,
261
262    CrossSigningReset,
266
267    Unknown(String),
269}
270
271impl core::fmt::Display for AccountManagementAction {
272    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
273        match self {
274            Self::Profile => write!(f, "org.matrix.profile"),
275            Self::SessionsList => write!(f, "org.matrix.sessions_list"),
276            Self::SessionView => write!(f, "org.matrix.session_view"),
277            Self::SessionEnd => write!(f, "org.matrix.session_end"),
278            Self::AccountDeactivate => write!(f, "org.matrix.account_deactivate"),
279            Self::CrossSigningReset => write!(f, "org.matrix.cross_signing_reset"),
280            Self::Unknown(value) => write!(f, "{value}"),
281        }
282    }
283}
284
285impl core::str::FromStr for AccountManagementAction {
286    type Err = core::convert::Infallible;
287
288    fn from_str(s: &str) -> Result<Self, Self::Err> {
289        match s {
290            "org.matrix.profile" => Ok(Self::Profile),
291            "org.matrix.sessions_list" => Ok(Self::SessionsList),
292            "org.matrix.session_view" => Ok(Self::SessionView),
293            "org.matrix.session_end" => Ok(Self::SessionEnd),
294            "org.matrix.account_deactivate" => Ok(Self::AccountDeactivate),
295            "org.matrix.cross_signing_reset" => Ok(Self::CrossSigningReset),
296            value => Ok(Self::Unknown(value.to_owned())),
297        }
298    }
299}
300
301pub static DEFAULT_RESPONSE_MODES_SUPPORTED: &[ResponseMode] =
303    &[ResponseMode::Query, ResponseMode::Fragment];
304
305pub static DEFAULT_GRANT_TYPES_SUPPORTED: &[GrantType] =
307    &[GrantType::AuthorizationCode, GrantType::Implicit];
308
309pub static DEFAULT_AUTH_METHODS_SUPPORTED: &[OAuthClientAuthenticationMethod] =
312    &[OAuthClientAuthenticationMethod::ClientSecretBasic];
313
314pub static DEFAULT_CLAIM_TYPES_SUPPORTED: &[ClaimType] = &[ClaimType::Normal];
316
317#[skip_serializing_none]
323#[derive(Debug, Serialize, Deserialize, Clone, Default)]
324pub struct ProviderMetadata {
325    pub issuer: Option<String>,
331
332    pub authorization_endpoint: Option<Url>,
339
340    pub token_endpoint: Option<Url>,
347
348    pub jwks_uri: Option<Url>,
354
355    pub registration_endpoint: Option<Url>,
362
363    pub scopes_supported: Option<Vec<String>>,
369
370    pub response_types_supported: Option<Vec<ResponseType>>,
377
378    pub response_modes_supported: Option<Vec<ResponseMode>>,
385
386    pub grant_types_supported: Option<Vec<GrantType>>,
393
394    pub token_endpoint_auth_methods_supported: Option<Vec<OAuthClientAuthenticationMethod>>,
399
400    pub token_endpoint_auth_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
410
411    pub service_documentation: Option<Url>,
414
415    pub ui_locales_supported: Option<Vec<LanguageTag>>,
420
421    pub op_policy_uri: Option<Url>,
425
426    pub op_tos_uri: Option<Url>,
429
430    pub revocation_endpoint: Option<Url>,
437
438    pub revocation_endpoint_auth_methods_supported: Option<Vec<OAuthClientAuthenticationMethod>>,
443
444    pub revocation_endpoint_auth_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
454
455    pub introspection_endpoint: Option<Url>,
461
462    pub introspection_endpoint_auth_methods_supported:
465        Option<Vec<AuthenticationMethodOrAccessTokenType>>,
466
467    pub introspection_endpoint_auth_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
477
478    pub code_challenge_methods_supported: Option<Vec<PkceCodeChallengeMethod>>,
483
484    pub userinfo_endpoint: Option<Url>,
488
489    pub acr_values_supported: Option<Vec<String>>,
492
493    pub subject_types_supported: Option<Vec<SubjectType>>,
498
499    pub id_token_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
504
505    pub id_token_encryption_alg_values_supported: Option<Vec<JsonWebEncryptionAlg>>,
508
509    pub id_token_encryption_enc_values_supported: Option<Vec<JsonWebEncryptionEnc>>,
512
513    pub userinfo_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
516
517    pub userinfo_encryption_alg_values_supported: Option<Vec<JsonWebEncryptionAlg>>,
520
521    pub userinfo_encryption_enc_values_supported: Option<Vec<JsonWebEncryptionEnc>>,
524
525    pub request_object_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
528
529    pub request_object_encryption_alg_values_supported: Option<Vec<JsonWebEncryptionAlg>>,
532
533    pub request_object_encryption_enc_values_supported: Option<Vec<JsonWebEncryptionEnc>>,
536
537    pub display_values_supported: Option<Vec<Display>>,
540
541    pub claim_types_supported: Option<Vec<ClaimType>>,
546
547    pub claims_supported: Option<Vec<String>>,
550
551    pub claims_locales_supported: Option<Vec<LanguageTag>>,
554
555    pub claims_parameter_supported: Option<bool>,
560
561    pub request_parameter_supported: Option<bool>,
566
567    pub request_uri_parameter_supported: Option<bool>,
572
573    pub require_request_uri_registration: Option<bool>,
578
579    pub require_signed_request_object: Option<bool>,
586
587    pub pushed_authorization_request_endpoint: Option<Url>,
592
593    pub require_pushed_authorization_requests: Option<bool>,
598
599    pub prompt_values_supported: Option<Vec<Prompt>>,
606
607    pub device_authorization_endpoint: Option<Url>,
611
612    pub end_session_endpoint: Option<Url>,
616
617    pub account_management_uri: Option<Url>,
622
623    pub account_management_actions_supported: Option<Vec<AccountManagementAction>>,
627}
628
629impl ProviderMetadata {
630    pub fn validate(
644        self,
645        issuer: &str,
646    ) -> Result<VerifiedProviderMetadata, ProviderMetadataVerificationError> {
647        let metadata = self.insecure_verify_metadata()?;
648
649        if metadata.issuer() != issuer {
650            return Err(ProviderMetadataVerificationError::IssuerUrlsDontMatch);
651        }
652
653        validate_url(
654            "issuer",
655            &metadata
656                .issuer()
657                .parse()
658                .map_err(|_| ProviderMetadataVerificationError::IssuerNotUrl)?,
659            ExtraUrlRestrictions::NoQueryOrFragment,
660        )?;
661
662        validate_url(
663            "authorization_endpoint",
664            metadata.authorization_endpoint(),
665            ExtraUrlRestrictions::NoFragment,
666        )?;
667
668        validate_url(
669            "token_endpoint",
670            metadata.token_endpoint(),
671            ExtraUrlRestrictions::NoFragment,
672        )?;
673
674        validate_url("jwks_uri", metadata.jwks_uri(), ExtraUrlRestrictions::None)?;
675
676        if let Some(url) = &metadata.registration_endpoint {
677            validate_url("registration_endpoint", url, ExtraUrlRestrictions::None)?;
678        }
679
680        if let Some(scopes) = &metadata.scopes_supported {
681            if !scopes.iter().any(|s| s == "openid") {
682                return Err(ProviderMetadataVerificationError::ScopesMissingOpenid);
683            }
684        }
685
686        validate_signing_alg_values_supported(
687            "token_endpoint",
688            metadata
689                .token_endpoint_auth_signing_alg_values_supported
690                .iter()
691                .flatten(),
692            metadata
693                .token_endpoint_auth_methods_supported
694                .iter()
695                .flatten(),
696        )?;
697
698        if let Some(url) = &metadata.revocation_endpoint {
699            validate_url("revocation_endpoint", url, ExtraUrlRestrictions::NoFragment)?;
700        }
701
702        validate_signing_alg_values_supported(
703            "revocation_endpoint",
704            metadata
705                .revocation_endpoint_auth_signing_alg_values_supported
706                .iter()
707                .flatten(),
708            metadata
709                .revocation_endpoint_auth_methods_supported
710                .iter()
711                .flatten(),
712        )?;
713
714        if let Some(url) = &metadata.introspection_endpoint {
715            validate_url("introspection_endpoint", url, ExtraUrlRestrictions::None)?;
716        }
717
718        let introspection_methods = metadata
721            .introspection_endpoint_auth_methods_supported
722            .as_ref()
723            .map(|v| {
724                v.iter()
725                    .filter_map(AuthenticationMethodOrAccessTokenType::authentication_method)
726                    .collect::<Vec<_>>()
727            });
728        validate_signing_alg_values_supported(
729            "introspection_endpoint",
730            metadata
731                .introspection_endpoint_auth_signing_alg_values_supported
732                .iter()
733                .flatten(),
734            introspection_methods.into_iter().flatten(),
735        )?;
736
737        if let Some(url) = &metadata.userinfo_endpoint {
738            validate_url("userinfo_endpoint", url, ExtraUrlRestrictions::None)?;
739        }
740
741        if let Some(url) = &metadata.pushed_authorization_request_endpoint {
742            validate_url(
743                "pushed_authorization_request_endpoint",
744                url,
745                ExtraUrlRestrictions::None,
746            )?;
747        }
748
749        if let Some(url) = &metadata.end_session_endpoint {
750            validate_url("end_session_endpoint", url, ExtraUrlRestrictions::None)?;
751        }
752
753        Ok(metadata)
754    }
755
756    pub fn insecure_verify_metadata(
778        self,
779    ) -> Result<VerifiedProviderMetadata, ProviderMetadataVerificationError> {
780        self.issuer
781            .as_ref()
782            .ok_or(ProviderMetadataVerificationError::MissingIssuer)?;
783
784        self.authorization_endpoint
785            .as_ref()
786            .ok_or(ProviderMetadataVerificationError::MissingAuthorizationEndpoint)?;
787
788        self.token_endpoint
789            .as_ref()
790            .ok_or(ProviderMetadataVerificationError::MissingTokenEndpoint)?;
791
792        self.jwks_uri
793            .as_ref()
794            .ok_or(ProviderMetadataVerificationError::MissingJwksUri)?;
795
796        self.response_types_supported
797            .as_ref()
798            .ok_or(ProviderMetadataVerificationError::MissingResponseTypesSupported)?;
799
800        self.subject_types_supported
801            .as_ref()
802            .ok_or(ProviderMetadataVerificationError::MissingSubjectTypesSupported)?;
803
804        self.id_token_signing_alg_values_supported
805            .as_ref()
806            .ok_or(ProviderMetadataVerificationError::MissingIdTokenSigningAlgValuesSupported)?;
807
808        Ok(VerifiedProviderMetadata { inner: self })
809    }
810
811    #[must_use]
816    pub fn response_modes_supported(&self) -> &[ResponseMode] {
817        self.response_modes_supported
818            .as_deref()
819            .unwrap_or(DEFAULT_RESPONSE_MODES_SUPPORTED)
820    }
821
822    #[must_use]
827    pub fn grant_types_supported(&self) -> &[GrantType] {
828        self.grant_types_supported
829            .as_deref()
830            .unwrap_or(DEFAULT_GRANT_TYPES_SUPPORTED)
831    }
832
833    #[must_use]
838    pub fn token_endpoint_auth_methods_supported(&self) -> &[OAuthClientAuthenticationMethod] {
839        self.token_endpoint_auth_methods_supported
840            .as_deref()
841            .unwrap_or(DEFAULT_AUTH_METHODS_SUPPORTED)
842    }
843
844    #[must_use]
849    pub fn revocation_endpoint_auth_methods_supported(&self) -> &[OAuthClientAuthenticationMethod] {
850        self.revocation_endpoint_auth_methods_supported
851            .as_deref()
852            .unwrap_or(DEFAULT_AUTH_METHODS_SUPPORTED)
853    }
854
855    #[must_use]
860    pub fn claim_types_supported(&self) -> &[ClaimType] {
861        self.claim_types_supported
862            .as_deref()
863            .unwrap_or(DEFAULT_CLAIM_TYPES_SUPPORTED)
864    }
865
866    #[must_use]
871    pub fn claims_parameter_supported(&self) -> bool {
872        self.claims_parameter_supported.unwrap_or(false)
873    }
874
875    #[must_use]
880    pub fn request_parameter_supported(&self) -> bool {
881        self.request_parameter_supported.unwrap_or(false)
882    }
883
884    #[must_use]
889    pub fn request_uri_parameter_supported(&self) -> bool {
890        self.request_uri_parameter_supported.unwrap_or(true)
891    }
892
893    #[must_use]
898    pub fn require_request_uri_registration(&self) -> bool {
899        self.require_request_uri_registration.unwrap_or(false)
900    }
901
902    #[must_use]
907    pub fn require_signed_request_object(&self) -> bool {
908        self.require_signed_request_object.unwrap_or(false)
909    }
910
911    #[must_use]
916    pub fn require_pushed_authorization_requests(&self) -> bool {
917        self.require_pushed_authorization_requests.unwrap_or(false)
918    }
919}
920
921#[derive(Debug, Clone)]
930pub struct VerifiedProviderMetadata {
931    inner: ProviderMetadata,
932}
933
934impl VerifiedProviderMetadata {
935    #[must_use]
937    pub fn issuer(&self) -> &str {
938        match &self.issuer {
939            Some(u) => u,
940            None => unreachable!(),
941        }
942    }
943
944    #[must_use]
946    pub fn authorization_endpoint(&self) -> &Url {
947        match &self.authorization_endpoint {
948            Some(u) => u,
949            None => unreachable!(),
950        }
951    }
952
953    #[must_use]
955    pub fn userinfo_endpoint(&self) -> &Url {
956        match &self.userinfo_endpoint {
957            Some(u) => u,
958            None => unreachable!(),
959        }
960    }
961
962    #[must_use]
964    pub fn token_endpoint(&self) -> &Url {
965        match &self.token_endpoint {
966            Some(u) => u,
967            None => unreachable!(),
968        }
969    }
970
971    #[must_use]
973    pub fn jwks_uri(&self) -> &Url {
974        match &self.jwks_uri {
975            Some(u) => u,
976            None => unreachable!(),
977        }
978    }
979
980    #[must_use]
983    pub fn response_types_supported(&self) -> &[ResponseType] {
984        match &self.response_types_supported {
985            Some(u) => u,
986            None => unreachable!(),
987        }
988    }
989
990    #[must_use]
993    pub fn subject_types_supported(&self) -> &[SubjectType] {
994        match &self.subject_types_supported {
995            Some(u) => u,
996            None => unreachable!(),
997        }
998    }
999
1000    #[must_use]
1003    pub fn id_token_signing_alg_values_supported(&self) -> &[JsonWebSignatureAlg] {
1004        match &self.id_token_signing_alg_values_supported {
1005            Some(u) => u,
1006            None => unreachable!(),
1007        }
1008    }
1009}
1010
1011impl Deref for VerifiedProviderMetadata {
1012    type Target = ProviderMetadata;
1013
1014    fn deref(&self) -> &Self::Target {
1015        &self.inner
1016    }
1017}
1018
1019#[derive(Debug, Error)]
1021pub enum ProviderMetadataVerificationError {
1022    #[error("issuer is missing")]
1024    MissingIssuer,
1025
1026    #[error("issuer is not a valid URL")]
1028    IssuerNotUrl,
1029
1030    #[error("authorization endpoint is missing")]
1032    MissingAuthorizationEndpoint,
1033
1034    #[error("token endpoint is missing")]
1036    MissingTokenEndpoint,
1037
1038    #[error("JWK Set URI is missing")]
1040    MissingJwksUri,
1041
1042    #[error("supported response types are missing")]
1044    MissingResponseTypesSupported,
1045
1046    #[error("supported subject types are missing")]
1048    MissingSubjectTypesSupported,
1049
1050    #[error("supported ID token signing algorithm values are missing")]
1052    MissingIdTokenSigningAlgValuesSupported,
1053
1054    #[error("{0}'s URL doesn't use a https scheme: {1}")]
1056    UrlNonHttpsScheme(&'static str, Url),
1057
1058    #[error("{0}'s URL contains a query: {1}")]
1060    UrlWithQuery(&'static str, Url),
1061
1062    #[error("{0}'s URL contains a fragment: {1}")]
1064    UrlWithFragment(&'static str, Url),
1065
1066    #[error("issuer URLs don't match")]
1068    IssuerUrlsDontMatch,
1069
1070    #[error("missing openid scope")]
1072    ScopesMissingOpenid,
1073
1074    #[error("missing `code` response type")]
1076    ResponseTypesMissingCode,
1077
1078    #[error("missing `id_token` response type")]
1080    ResponseTypesMissingIdToken,
1081
1082    #[error("missing `id_token token` response type")]
1084    ResponseTypesMissingIdTokenToken,
1085
1086    #[error("missing `authorization_code` grant type")]
1088    GrantTypesMissingAuthorizationCode,
1089
1090    #[error("missing `implicit` grant type")]
1092    GrantTypesMissingImplicit,
1093
1094    #[error("{0} missing auth signing algorithm values")]
1098    MissingAuthSigningAlgValues(&'static str),
1099
1100    #[error("{0} signing algorithm values contain `none`")]
1103    SigningAlgValuesWithNone(&'static str),
1104}
1105
1106#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1108enum ExtraUrlRestrictions {
1109    None,
1111
1112    NoFragment,
1114
1115    NoQueryOrFragment,
1117}
1118
1119impl ExtraUrlRestrictions {
1120    fn can_have_fragment(self) -> bool {
1121        self == Self::None
1122    }
1123
1124    fn can_have_query(self) -> bool {
1125        self != Self::NoQueryOrFragment
1126    }
1127}
1128
1129fn validate_url(
1133    field: &'static str,
1134    url: &Url,
1135    restrictions: ExtraUrlRestrictions,
1136) -> Result<(), ProviderMetadataVerificationError> {
1137    if url.scheme() != "https" {
1138        return Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(
1139            field,
1140            url.clone(),
1141        ));
1142    }
1143
1144    if !restrictions.can_have_query() && url.query().is_some() {
1145        return Err(ProviderMetadataVerificationError::UrlWithQuery(
1146            field,
1147            url.clone(),
1148        ));
1149    }
1150
1151    if !restrictions.can_have_fragment() && url.fragment().is_some() {
1152        return Err(ProviderMetadataVerificationError::UrlWithFragment(
1153            field,
1154            url.clone(),
1155        ));
1156    }
1157
1158    Ok(())
1159}
1160
1161fn validate_signing_alg_values_supported<'a>(
1169    endpoint: &'static str,
1170    values: impl Iterator<Item = &'a JsonWebSignatureAlg>,
1171    mut methods: impl Iterator<Item = &'a OAuthClientAuthenticationMethod>,
1172) -> Result<(), ProviderMetadataVerificationError> {
1173    let mut no_values = true;
1174
1175    for value in values {
1176        if *value == JsonWebSignatureAlg::None {
1177            return Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(
1178                endpoint,
1179            ));
1180        }
1181
1182        no_values = false;
1183    }
1184
1185    if no_values
1186        && methods.any(|method| {
1187            matches!(
1188                method,
1189                OAuthClientAuthenticationMethod::ClientSecretJwt
1190                    | OAuthClientAuthenticationMethod::PrivateKeyJwt
1191            )
1192        })
1193    {
1194        return Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint));
1195    }
1196
1197    Ok(())
1198}
1199
1200#[skip_serializing_none]
1204#[serde_as]
1205#[derive(Default, Serialize, Deserialize, Clone)]
1206pub struct RpInitiatedLogoutRequest {
1207    pub id_token_hint: Option<String>,
1212
1213    pub logout_hint: Option<String>,
1220
1221    pub client_id: Option<String>,
1230
1231    pub post_logout_redirect_uri: Option<Url>,
1237
1238    pub state: Option<String>,
1242
1243    #[serde_as(as = "Option<StringWithSeparator::<SpaceSeparator, LanguageTag>>")]
1246    #[serde(default)]
1247    pub ui_locales: Option<Vec<LanguageTag>>,
1248}
1249
1250impl fmt::Debug for RpInitiatedLogoutRequest {
1251    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1252        f.debug_struct("RpInitiatedLogoutRequest")
1253            .field("logout_hint", &self.logout_hint)
1254            .field("post_logout_redirect_uri", &self.post_logout_redirect_uri)
1255            .field("ui_locales", &self.ui_locales)
1256            .finish_non_exhaustive()
1257    }
1258}
1259
1260#[cfg(test)]
1261mod tests {
1262    use assert_matches::assert_matches;
1263    use mas_iana::{
1264        jose::JsonWebSignatureAlg,
1265        oauth::{OAuthAuthorizationEndpointResponseType, OAuthClientAuthenticationMethod},
1266    };
1267    use url::Url;
1268
1269    use super::*;
1270
1271    fn valid_provider_metadata() -> (ProviderMetadata, String) {
1272        let issuer = "https://localhost".to_owned();
1273        let metadata = ProviderMetadata {
1274            issuer: Some(issuer.clone()),
1275            authorization_endpoint: Some(Url::parse("https://localhost/auth").unwrap()),
1276            token_endpoint: Some(Url::parse("https://localhost/token").unwrap()),
1277            jwks_uri: Some(Url::parse("https://localhost/jwks").unwrap()),
1278            response_types_supported: Some(vec![
1279                OAuthAuthorizationEndpointResponseType::Code.into(),
1280            ]),
1281            subject_types_supported: Some(vec![SubjectType::Public]),
1282            id_token_signing_alg_values_supported: Some(vec![JsonWebSignatureAlg::Rs256]),
1283            ..Default::default()
1284        };
1285
1286        (metadata, issuer)
1287    }
1288
1289    #[test]
1290    fn validate_required_metadata() {
1291        let (metadata, issuer) = valid_provider_metadata();
1292        metadata.validate(&issuer).unwrap();
1293    }
1294
1295    #[test]
1296    fn validate_issuer() {
1297        let (mut metadata, issuer) = valid_provider_metadata();
1298
1299        metadata.issuer = None;
1301        assert_matches!(
1302            metadata.clone().validate(&issuer),
1303            Err(ProviderMetadataVerificationError::MissingIssuer)
1304        );
1305
1306        metadata.issuer = Some("not-an-url".to_owned());
1308        assert_matches!(
1309            metadata.clone().validate("not-an-url"),
1310            Err(ProviderMetadataVerificationError::IssuerNotUrl)
1311        );
1312
1313        metadata.issuer = Some("https://example.com/".to_owned());
1315        assert_matches!(
1316            metadata.clone().validate(&issuer),
1317            Err(ProviderMetadataVerificationError::IssuerUrlsDontMatch)
1318        );
1319
1320        let issuer = "http://localhost/".to_owned();
1322        metadata.issuer = Some(issuer.clone());
1323        let (field, url) = assert_matches!(
1324            metadata.clone().validate(&issuer),
1325            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1326        );
1327        assert_eq!(field, "issuer");
1328        assert_eq!(url.as_str(), issuer);
1329
1330        let issuer = "https://localhost/?query".to_owned();
1332        metadata.issuer = Some(issuer.clone());
1333        let (field, url) = assert_matches!(
1334            metadata.clone().validate(&issuer),
1335            Err(ProviderMetadataVerificationError::UrlWithQuery(field, url)) => (field, url)
1336        );
1337        assert_eq!(field, "issuer");
1338        assert_eq!(url.as_str(), issuer);
1339
1340        let issuer = "https://localhost/#fragment".to_owned();
1342        metadata.issuer = Some(issuer.clone());
1343        let (field, url) = assert_matches!(
1344            metadata.clone().validate(&issuer),
1345            Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1346        );
1347        assert_eq!(field, "issuer");
1348        assert_eq!(url.as_str(), issuer);
1349
1350        let issuer = "https://localhost/issuer1".to_owned();
1352        metadata.issuer = Some(issuer.clone());
1353        metadata.validate(&issuer).unwrap();
1354    }
1355
1356    #[test]
1357    fn validate_authorization_endpoint() {
1358        let (mut metadata, issuer) = valid_provider_metadata();
1359
1360        metadata.authorization_endpoint = None;
1362        assert_matches!(
1363            metadata.clone().validate(&issuer),
1364            Err(ProviderMetadataVerificationError::MissingAuthorizationEndpoint)
1365        );
1366
1367        let endpoint = Url::parse("http://localhost/auth").unwrap();
1369        metadata.authorization_endpoint = Some(endpoint.clone());
1370        let (field, url) = assert_matches!(
1371            metadata.clone().validate(&issuer),
1372            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1373        );
1374        assert_eq!(field, "authorization_endpoint");
1375        assert_eq!(url, endpoint);
1376
1377        let endpoint = Url::parse("https://localhost/auth#fragment").unwrap();
1379        metadata.authorization_endpoint = Some(endpoint.clone());
1380        let (field, url) = assert_matches!(
1381            metadata.clone().validate(&issuer),
1382            Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1383        );
1384        assert_eq!(field, "authorization_endpoint");
1385        assert_eq!(url, endpoint);
1386
1387        metadata.authorization_endpoint = Some(Url::parse("https://localhost/auth?query").unwrap());
1389        metadata.validate(&issuer).unwrap();
1390    }
1391
1392    #[test]
1393    fn validate_token_endpoint() {
1394        let (mut metadata, issuer) = valid_provider_metadata();
1395
1396        metadata.token_endpoint = None;
1398        assert_matches!(
1399            metadata.clone().validate(&issuer),
1400            Err(ProviderMetadataVerificationError::MissingTokenEndpoint)
1401        );
1402
1403        let endpoint = Url::parse("http://localhost/token").unwrap();
1405        metadata.token_endpoint = Some(endpoint.clone());
1406        let (field, url) = assert_matches!(
1407            metadata.clone().validate(&issuer),
1408            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1409        );
1410        assert_eq!(field, "token_endpoint");
1411        assert_eq!(url, endpoint);
1412
1413        let endpoint = Url::parse("https://localhost/token#fragment").unwrap();
1415        metadata.token_endpoint = Some(endpoint.clone());
1416        let (field, url) = assert_matches!(
1417            metadata.clone().validate(&issuer),
1418            Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1419        );
1420        assert_eq!(field, "token_endpoint");
1421        assert_eq!(url, endpoint);
1422
1423        metadata.token_endpoint = Some(Url::parse("https://localhost/token?query").unwrap());
1425        metadata.validate(&issuer).unwrap();
1426    }
1427
1428    #[test]
1429    fn validate_jwks_uri() {
1430        let (mut metadata, issuer) = valid_provider_metadata();
1431
1432        metadata.jwks_uri = None;
1434        assert_matches!(
1435            metadata.clone().validate(&issuer),
1436            Err(ProviderMetadataVerificationError::MissingJwksUri)
1437        );
1438
1439        let endpoint = Url::parse("http://localhost/jwks").unwrap();
1441        metadata.jwks_uri = Some(endpoint.clone());
1442        let (field, url) = assert_matches!(
1443            metadata.clone().validate(&issuer),
1444            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1445        );
1446        assert_eq!(field, "jwks_uri");
1447        assert_eq!(url, endpoint);
1448
1449        metadata.jwks_uri = Some(Url::parse("https://localhost/token?query#fragment").unwrap());
1451        metadata.validate(&issuer).unwrap();
1452    }
1453
1454    #[test]
1455    fn validate_registration_endpoint() {
1456        let (mut metadata, issuer) = valid_provider_metadata();
1457
1458        let endpoint = Url::parse("http://localhost/registration").unwrap();
1460        metadata.registration_endpoint = Some(endpoint.clone());
1461        let (field, url) = assert_matches!(
1462            metadata.clone().validate(&issuer),
1463            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1464        );
1465        assert_eq!(field, "registration_endpoint");
1466        assert_eq!(url, endpoint);
1467
1468        metadata.registration_endpoint = None;
1470        metadata.clone().validate(&issuer).unwrap();
1471
1472        metadata.registration_endpoint =
1474            Some(Url::parse("https://localhost/registration?query#fragment").unwrap());
1475        metadata.validate(&issuer).unwrap();
1476    }
1477
1478    #[test]
1479    fn validate_scopes_supported() {
1480        let (mut metadata, issuer) = valid_provider_metadata();
1481
1482        metadata.scopes_supported = Some(vec!["custom".to_owned()]);
1484        assert_matches!(
1485            metadata.clone().validate(&issuer),
1486            Err(ProviderMetadataVerificationError::ScopesMissingOpenid)
1487        );
1488
1489        metadata.scopes_supported = None;
1491        metadata.clone().validate(&issuer).unwrap();
1492
1493        metadata.scopes_supported = Some(vec!["openid".to_owned(), "custom".to_owned()]);
1495        metadata.validate(&issuer).unwrap();
1496    }
1497
1498    #[test]
1499    fn validate_response_types_supported() {
1500        let (mut metadata, issuer) = valid_provider_metadata();
1501
1502        metadata.response_types_supported = None;
1504        assert_matches!(
1505            metadata.clone().validate(&issuer),
1506            Err(ProviderMetadataVerificationError::MissingResponseTypesSupported)
1507        );
1508
1509        metadata.response_types_supported =
1511            Some(vec![OAuthAuthorizationEndpointResponseType::Code.into()]);
1512        metadata.validate(&issuer).unwrap();
1513    }
1514
1515    #[test]
1516    fn validate_token_endpoint_signing_alg_values_supported() {
1517        let (mut metadata, issuer) = valid_provider_metadata();
1518
1519        metadata.token_endpoint_auth_signing_alg_values_supported = None;
1521        metadata.token_endpoint_auth_methods_supported = None;
1522        metadata.clone().validate(&issuer).unwrap();
1523
1524        metadata.token_endpoint_auth_signing_alg_values_supported =
1526            Some(vec![JsonWebSignatureAlg::None]);
1527        let endpoint = assert_matches!(
1528            metadata.clone().validate(&issuer),
1529            Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(endpoint)) => endpoint
1530        );
1531        assert_eq!(endpoint, "token_endpoint");
1532
1533        metadata.token_endpoint_auth_signing_alg_values_supported =
1535            Some(vec![JsonWebSignatureAlg::Rs256, JsonWebSignatureAlg::EdDsa]);
1536        metadata.clone().validate(&issuer).unwrap();
1537
1538        metadata.token_endpoint_auth_methods_supported =
1540            Some(vec![OAuthClientAuthenticationMethod::ClientSecretJwt]);
1541        metadata.token_endpoint_auth_signing_alg_values_supported = None;
1542        let endpoint = assert_matches!(
1543            metadata.clone().validate(&issuer),
1544            Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint)) => endpoint
1545        );
1546        assert_eq!(endpoint, "token_endpoint");
1547
1548        metadata.token_endpoint_auth_signing_alg_values_supported =
1550            Some(vec![JsonWebSignatureAlg::Rs256]);
1551        metadata.clone().validate(&issuer).unwrap();
1552
1553        metadata.token_endpoint_auth_methods_supported =
1555            Some(vec![OAuthClientAuthenticationMethod::PrivateKeyJwt]);
1556        metadata.token_endpoint_auth_signing_alg_values_supported = None;
1557        let endpoint = assert_matches!(
1558            metadata.clone().validate(&issuer),
1559            Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint)) => endpoint
1560        );
1561        assert_eq!(endpoint, "token_endpoint");
1562
1563        metadata.token_endpoint_auth_signing_alg_values_supported =
1565            Some(vec![JsonWebSignatureAlg::Rs256]);
1566        metadata.clone().validate(&issuer).unwrap();
1567
1568        metadata.token_endpoint_auth_methods_supported = Some(vec![
1570            OAuthClientAuthenticationMethod::ClientSecretBasic,
1571            OAuthClientAuthenticationMethod::ClientSecretPost,
1572        ]);
1573        metadata.token_endpoint_auth_signing_alg_values_supported = None;
1574        metadata.validate(&issuer).unwrap();
1575    }
1576
1577    #[test]
1578    fn validate_revocation_endpoint() {
1579        let (mut metadata, issuer) = valid_provider_metadata();
1580
1581        metadata.revocation_endpoint = None;
1583        metadata.clone().validate(&issuer).unwrap();
1584
1585        let endpoint = Url::parse("http://localhost/revocation").unwrap();
1587        metadata.revocation_endpoint = Some(endpoint.clone());
1588        let (field, url) = assert_matches!(
1589            metadata.clone().validate(&issuer),
1590            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1591        );
1592        assert_eq!(field, "revocation_endpoint");
1593        assert_eq!(url, endpoint);
1594
1595        let endpoint = Url::parse("https://localhost/revocation#fragment").unwrap();
1597        metadata.revocation_endpoint = Some(endpoint.clone());
1598        let (field, url) = assert_matches!(
1599            metadata.clone().validate(&issuer),
1600            Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1601        );
1602        assert_eq!(field, "revocation_endpoint");
1603        assert_eq!(url, endpoint);
1604
1605        metadata.revocation_endpoint =
1607            Some(Url::parse("https://localhost/revocation?query").unwrap());
1608        metadata.validate(&issuer).unwrap();
1609    }
1610
1611    #[test]
1612    fn validate_revocation_endpoint_signing_alg_values_supported() {
1613        let (mut metadata, issuer) = valid_provider_metadata();
1614
1615        metadata.revocation_endpoint_auth_signing_alg_values_supported = None;
1620        metadata.revocation_endpoint_auth_methods_supported = None;
1621        metadata.clone().validate(&issuer).unwrap();
1622
1623        metadata.revocation_endpoint_auth_signing_alg_values_supported =
1625            Some(vec![JsonWebSignatureAlg::None]);
1626        let endpoint = assert_matches!(
1627            metadata.validate(&issuer),
1628            Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(endpoint)) => endpoint
1629        );
1630        assert_eq!(endpoint, "revocation_endpoint");
1631    }
1632
1633    #[test]
1634    fn validate_introspection_endpoint() {
1635        let (mut metadata, issuer) = valid_provider_metadata();
1636
1637        metadata.introspection_endpoint = None;
1639        metadata.clone().validate(&issuer).unwrap();
1640
1641        let endpoint = Url::parse("http://localhost/introspection").unwrap();
1643        metadata.introspection_endpoint = Some(endpoint.clone());
1644        let (field, url) = assert_matches!(
1645            metadata.clone().validate(&issuer),
1646            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1647        );
1648        assert_eq!(field, "introspection_endpoint");
1649        assert_eq!(url, endpoint);
1650
1651        metadata.introspection_endpoint =
1653            Some(Url::parse("https://localhost/introspection?query#fragment").unwrap());
1654        metadata.validate(&issuer).unwrap();
1655    }
1656
1657    #[test]
1658    fn validate_introspection_endpoint_signing_alg_values_supported() {
1659        let (mut metadata, issuer) = valid_provider_metadata();
1660
1661        metadata.introspection_endpoint_auth_signing_alg_values_supported = None;
1666        metadata.introspection_endpoint_auth_methods_supported = None;
1667        metadata.clone().validate(&issuer).unwrap();
1668
1669        metadata.introspection_endpoint_auth_signing_alg_values_supported =
1671            Some(vec![JsonWebSignatureAlg::None]);
1672        let endpoint = assert_matches!(
1673            metadata.validate(&issuer),
1674            Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(endpoint)) => endpoint
1675        );
1676        assert_eq!(endpoint, "introspection_endpoint");
1677    }
1678
1679    #[test]
1680    fn validate_userinfo_endpoint() {
1681        let (mut metadata, issuer) = valid_provider_metadata();
1682
1683        metadata.userinfo_endpoint = None;
1685        metadata.clone().validate(&issuer).unwrap();
1686
1687        let endpoint = Url::parse("http://localhost/userinfo").unwrap();
1689        metadata.userinfo_endpoint = Some(endpoint.clone());
1690        let (field, url) = assert_matches!(
1691            metadata.clone().validate(&issuer),
1692            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1693        );
1694        assert_eq!(field, "userinfo_endpoint");
1695        assert_eq!(url, endpoint);
1696
1697        metadata.userinfo_endpoint =
1699            Some(Url::parse("https://localhost/userinfo?query#fragment").unwrap());
1700        metadata.validate(&issuer).unwrap();
1701    }
1702
1703    #[test]
1704    fn validate_subject_types_supported() {
1705        let (mut metadata, issuer) = valid_provider_metadata();
1706
1707        metadata.subject_types_supported = None;
1709        assert_matches!(
1710            metadata.clone().validate(&issuer),
1711            Err(ProviderMetadataVerificationError::MissingSubjectTypesSupported)
1712        );
1713
1714        metadata.subject_types_supported = Some(vec![SubjectType::Public, SubjectType::Pairwise]);
1716        metadata.validate(&issuer).unwrap();
1717    }
1718
1719    #[test]
1720    fn validate_id_token_signing_alg_values_supported() {
1721        let (mut metadata, issuer) = valid_provider_metadata();
1722
1723        metadata.id_token_signing_alg_values_supported = None;
1725        assert_matches!(
1726            metadata.clone().validate(&issuer),
1727            Err(ProviderMetadataVerificationError::MissingIdTokenSigningAlgValuesSupported)
1728        );
1729
1730        metadata.id_token_signing_alg_values_supported =
1732            Some(vec![JsonWebSignatureAlg::Rs256, JsonWebSignatureAlg::EdDsa]);
1733        metadata.validate(&issuer).unwrap();
1734    }
1735
1736    #[test]
1737    fn validate_pushed_authorization_request_endpoint() {
1738        let (mut metadata, issuer) = valid_provider_metadata();
1739
1740        metadata.pushed_authorization_request_endpoint = None;
1742        metadata.clone().validate(&issuer).unwrap();
1743
1744        let endpoint = Url::parse("http://localhost/par").unwrap();
1746        metadata.pushed_authorization_request_endpoint = Some(endpoint.clone());
1747        let (field, url) = assert_matches!(
1748            metadata.clone().validate(&issuer),
1749            Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1750        );
1751        assert_eq!(field, "pushed_authorization_request_endpoint");
1752        assert_eq!(url, endpoint);
1753
1754        metadata.pushed_authorization_request_endpoint =
1756            Some(Url::parse("https://localhost/par?query#fragment").unwrap());
1757        metadata.validate(&issuer).unwrap();
1758    }
1759
1760    #[test]
1761    fn serialize_application_type() {
1762        assert_eq!(
1763            serde_json::to_string(&ApplicationType::Web).unwrap(),
1764            "\"web\""
1765        );
1766        assert_eq!(
1767            serde_json::to_string(&ApplicationType::Native).unwrap(),
1768            "\"native\""
1769        );
1770    }
1771
1772    #[test]
1773    fn deserialize_application_type() {
1774        assert_eq!(
1775            serde_json::from_str::<ApplicationType>("\"web\"").unwrap(),
1776            ApplicationType::Web
1777        );
1778        assert_eq!(
1779            serde_json::from_str::<ApplicationType>("\"native\"").unwrap(),
1780            ApplicationType::Native
1781        );
1782    }
1783
1784    #[test]
1785    fn serialize_subject_type() {
1786        assert_eq!(
1787            serde_json::to_string(&SubjectType::Public).unwrap(),
1788            "\"public\""
1789        );
1790        assert_eq!(
1791            serde_json::to_string(&SubjectType::Pairwise).unwrap(),
1792            "\"pairwise\""
1793        );
1794    }
1795
1796    #[test]
1797    fn deserialize_subject_type() {
1798        assert_eq!(
1799            serde_json::from_str::<SubjectType>("\"public\"").unwrap(),
1800            SubjectType::Public
1801        );
1802        assert_eq!(
1803            serde_json::from_str::<SubjectType>("\"pairwise\"").unwrap(),
1804            SubjectType::Pairwise
1805        );
1806    }
1807
1808    #[test]
1809    fn serialize_claim_type() {
1810        assert_eq!(
1811            serde_json::to_string(&ClaimType::Normal).unwrap(),
1812            "\"normal\""
1813        );
1814        assert_eq!(
1815            serde_json::to_string(&ClaimType::Aggregated).unwrap(),
1816            "\"aggregated\""
1817        );
1818        assert_eq!(
1819            serde_json::to_string(&ClaimType::Distributed).unwrap(),
1820            "\"distributed\""
1821        );
1822    }
1823
1824    #[test]
1825    fn deserialize_claim_type() {
1826        assert_eq!(
1827            serde_json::from_str::<ClaimType>("\"normal\"").unwrap(),
1828            ClaimType::Normal
1829        );
1830        assert_eq!(
1831            serde_json::from_str::<ClaimType>("\"aggregated\"").unwrap(),
1832            ClaimType::Aggregated
1833        );
1834        assert_eq!(
1835            serde_json::from_str::<ClaimType>("\"distributed\"").unwrap(),
1836            ClaimType::Distributed
1837        );
1838    }
1839
1840    #[test]
1841    fn deserialize_auth_method_or_token_type_type() {
1842        assert_eq!(
1843            serde_json::from_str::<AuthenticationMethodOrAccessTokenType>("\"none\"").unwrap(),
1844            AuthenticationMethodOrAccessTokenType::AuthenticationMethod(
1845                OAuthClientAuthenticationMethod::None
1846            )
1847        );
1848        assert_eq!(
1849            serde_json::from_str::<AuthenticationMethodOrAccessTokenType>("\"Bearer\"").unwrap(),
1850            AuthenticationMethodOrAccessTokenType::AccessTokenType(OAuthAccessTokenType::Bearer)
1851        );
1852        assert_eq!(
1853            serde_json::from_str::<AuthenticationMethodOrAccessTokenType>("\"unknown_value\"")
1854                .unwrap(),
1855            AuthenticationMethodOrAccessTokenType::Unknown("unknown_value".to_owned())
1856        );
1857    }
1858}