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}