1use std::{fmt, ops::Deref};
20
21use language_tags::LanguageTag;
22use mas_iana::{
23 jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg},
24 oauth::{OAuthAccessTokenType, OAuthClientAuthenticationMethod, PkceCodeChallengeMethod},
25};
26use serde::{Deserialize, Serialize};
27use serde_with::{
28 formats::SpaceSeparator, serde_as, skip_serializing_none, DeserializeFromStr, SerializeDisplay,
29 StringWithSeparator,
30};
31use thiserror::Error;
32use url::Url;
33
34use crate::{
35 requests::{Display, GrantType, Prompt, ResponseMode},
36 response_type::ResponseType,
37};
38
39#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
42pub enum AuthenticationMethodOrAccessTokenType {
43 AuthenticationMethod(OAuthClientAuthenticationMethod),
45
46 AccessTokenType(OAuthAccessTokenType),
48
49 Unknown(String),
55}
56
57impl core::fmt::Display for AuthenticationMethodOrAccessTokenType {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 match self {
60 Self::AuthenticationMethod(m) => m.fmt(f),
61 Self::AccessTokenType(t) => t.fmt(f),
62 Self::Unknown(s) => s.fmt(f),
63 }
64 }
65}
66
67impl core::str::FromStr for AuthenticationMethodOrAccessTokenType {
68 type Err = core::convert::Infallible;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 match OAuthClientAuthenticationMethod::from_str(s) {
72 Ok(OAuthClientAuthenticationMethod::Unknown(_)) | Err(_) => {}
73 Ok(m) => return Ok(m.into()),
74 }
75
76 match OAuthAccessTokenType::from_str(s) {
77 Ok(OAuthAccessTokenType::Unknown(_)) | Err(_) => {}
78 Ok(m) => return Ok(m.into()),
79 }
80
81 Ok(Self::Unknown(s.to_owned()))
82 }
83}
84
85impl AuthenticationMethodOrAccessTokenType {
86 #[must_use]
89 pub fn authentication_method(&self) -> Option<&OAuthClientAuthenticationMethod> {
90 match self {
91 Self::AuthenticationMethod(m) => Some(m),
92 _ => None,
93 }
94 }
95
96 #[must_use]
99 pub fn access_token_type(&self) -> Option<&OAuthAccessTokenType> {
100 match self {
101 Self::AccessTokenType(t) => Some(t),
102 _ => None,
103 }
104 }
105}
106
107impl From<OAuthClientAuthenticationMethod> for AuthenticationMethodOrAccessTokenType {
108 fn from(t: OAuthClientAuthenticationMethod) -> Self {
109 Self::AuthenticationMethod(t)
110 }
111}
112
113impl From<OAuthAccessTokenType> for AuthenticationMethodOrAccessTokenType {
114 fn from(t: OAuthAccessTokenType) -> Self {
115 Self::AccessTokenType(t)
116 }
117}
118
119#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
121pub enum ApplicationType {
122 Web,
124
125 Native,
127
128 Unknown(String),
130}
131
132impl core::fmt::Display for ApplicationType {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 match self {
135 Self::Web => f.write_str("web"),
136 Self::Native => f.write_str("native"),
137 Self::Unknown(s) => f.write_str(s),
138 }
139 }
140}
141
142impl core::str::FromStr for ApplicationType {
143 type Err = core::convert::Infallible;
144
145 fn from_str(s: &str) -> Result<Self, Self::Err> {
146 match s {
147 "web" => Ok(Self::Web),
148 "native" => Ok(Self::Native),
149 s => Ok(Self::Unknown(s.to_owned())),
150 }
151 }
152}
153
154#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
160pub enum SubjectType {
161 Public,
163
164 Pairwise,
168
169 Unknown(String),
171}
172
173impl core::fmt::Display for SubjectType {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 match self {
176 Self::Public => f.write_str("public"),
177 Self::Pairwise => f.write_str("pairwise"),
178 Self::Unknown(s) => f.write_str(s),
179 }
180 }
181}
182
183impl core::str::FromStr for SubjectType {
184 type Err = core::convert::Infallible;
185
186 fn from_str(s: &str) -> Result<Self, Self::Err> {
187 match s {
188 "public" => Ok(Self::Public),
189 "pairwise" => Ok(Self::Pairwise),
190 s => Ok(Self::Unknown(s.to_owned())),
191 }
192 }
193}
194
195#[derive(SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, Debug)]
197pub enum ClaimType {
198 Normal,
200
201 Aggregated,
204
205 Distributed,
208
209 Unknown(String),
211}
212
213impl core::fmt::Display for ClaimType {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 match self {
216 Self::Normal => f.write_str("normal"),
217 Self::Aggregated => f.write_str("aggregated"),
218 Self::Distributed => f.write_str("distributed"),
219 Self::Unknown(s) => f.write_str(s),
220 }
221 }
222}
223
224impl core::str::FromStr for ClaimType {
225 type Err = core::convert::Infallible;
226
227 fn from_str(s: &str) -> Result<Self, Self::Err> {
228 match s {
229 "normal" => Ok(Self::Normal),
230 "aggregated" => Ok(Self::Aggregated),
231 "distributed" => Ok(Self::Distributed),
232 s => Ok(Self::Unknown(s.to_owned())),
233 }
234 }
235}
236
237#[derive(
241 SerializeDisplay, DeserializeFromStr, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
242)]
243#[non_exhaustive]
244pub enum AccountManagementAction {
245 Profile,
249
250 SessionsList,
254
255 SessionView,
259
260 SessionEnd,
264
265 AccountDeactivate,
269
270 CrossSigningReset,
274
275 Unknown(String),
277}
278
279impl core::fmt::Display for AccountManagementAction {
280 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
281 match self {
282 Self::Profile => write!(f, "org.matrix.profile"),
283 Self::SessionsList => write!(f, "org.matrix.sessions_list"),
284 Self::SessionView => write!(f, "org.matrix.session_view"),
285 Self::SessionEnd => write!(f, "org.matrix.session_end"),
286 Self::AccountDeactivate => write!(f, "org.matrix.account_deactivate"),
287 Self::CrossSigningReset => write!(f, "org.matrix.cross_signing_reset"),
288 Self::Unknown(value) => write!(f, "{value}"),
289 }
290 }
291}
292
293impl core::str::FromStr for AccountManagementAction {
294 type Err = core::convert::Infallible;
295
296 fn from_str(s: &str) -> Result<Self, Self::Err> {
297 match s {
298 "org.matrix.profile" => Ok(Self::Profile),
299 "org.matrix.sessions_list" => Ok(Self::SessionsList),
300 "org.matrix.session_view" => Ok(Self::SessionView),
301 "org.matrix.session_end" => Ok(Self::SessionEnd),
302 "org.matrix.account_deactivate" => Ok(Self::AccountDeactivate),
303 "org.matrix.cross_signing_reset" => Ok(Self::CrossSigningReset),
304 value => Ok(Self::Unknown(value.to_owned())),
305 }
306 }
307}
308
309pub static DEFAULT_RESPONSE_MODES_SUPPORTED: &[ResponseMode] =
311 &[ResponseMode::Query, ResponseMode::Fragment];
312
313pub static DEFAULT_GRANT_TYPES_SUPPORTED: &[GrantType] =
315 &[GrantType::AuthorizationCode, GrantType::Implicit];
316
317pub static DEFAULT_AUTH_METHODS_SUPPORTED: &[OAuthClientAuthenticationMethod] =
320 &[OAuthClientAuthenticationMethod::ClientSecretBasic];
321
322pub static DEFAULT_CLAIM_TYPES_SUPPORTED: &[ClaimType] = &[ClaimType::Normal];
324
325#[skip_serializing_none]
331#[derive(Debug, Serialize, Deserialize, Clone, Default)]
332pub struct ProviderMetadata {
333 pub issuer: Option<String>,
339
340 pub authorization_endpoint: Option<Url>,
347
348 pub token_endpoint: Option<Url>,
355
356 pub jwks_uri: Option<Url>,
362
363 pub registration_endpoint: Option<Url>,
370
371 pub scopes_supported: Option<Vec<String>>,
377
378 pub response_types_supported: Option<Vec<ResponseType>>,
385
386 pub response_modes_supported: Option<Vec<ResponseMode>>,
393
394 pub grant_types_supported: Option<Vec<GrantType>>,
401
402 pub token_endpoint_auth_methods_supported: Option<Vec<OAuthClientAuthenticationMethod>>,
407
408 pub token_endpoint_auth_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
418
419 pub service_documentation: Option<Url>,
422
423 pub ui_locales_supported: Option<Vec<LanguageTag>>,
428
429 pub op_policy_uri: Option<Url>,
433
434 pub op_tos_uri: Option<Url>,
437
438 pub revocation_endpoint: Option<Url>,
445
446 pub revocation_endpoint_auth_methods_supported: Option<Vec<OAuthClientAuthenticationMethod>>,
451
452 pub revocation_endpoint_auth_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
462
463 pub introspection_endpoint: Option<Url>,
469
470 pub introspection_endpoint_auth_methods_supported:
473 Option<Vec<AuthenticationMethodOrAccessTokenType>>,
474
475 pub introspection_endpoint_auth_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
485
486 pub code_challenge_methods_supported: Option<Vec<PkceCodeChallengeMethod>>,
491
492 pub userinfo_endpoint: Option<Url>,
496
497 pub acr_values_supported: Option<Vec<String>>,
500
501 pub subject_types_supported: Option<Vec<SubjectType>>,
506
507 pub id_token_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
512
513 pub id_token_encryption_alg_values_supported: Option<Vec<JsonWebEncryptionAlg>>,
516
517 pub id_token_encryption_enc_values_supported: Option<Vec<JsonWebEncryptionEnc>>,
520
521 pub userinfo_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
524
525 pub userinfo_encryption_alg_values_supported: Option<Vec<JsonWebEncryptionAlg>>,
528
529 pub userinfo_encryption_enc_values_supported: Option<Vec<JsonWebEncryptionEnc>>,
532
533 pub request_object_signing_alg_values_supported: Option<Vec<JsonWebSignatureAlg>>,
536
537 pub request_object_encryption_alg_values_supported: Option<Vec<JsonWebEncryptionAlg>>,
540
541 pub request_object_encryption_enc_values_supported: Option<Vec<JsonWebEncryptionEnc>>,
544
545 pub display_values_supported: Option<Vec<Display>>,
548
549 pub claim_types_supported: Option<Vec<ClaimType>>,
554
555 pub claims_supported: Option<Vec<String>>,
558
559 pub claims_locales_supported: Option<Vec<LanguageTag>>,
562
563 pub claims_parameter_supported: Option<bool>,
568
569 pub request_parameter_supported: Option<bool>,
574
575 pub request_uri_parameter_supported: Option<bool>,
580
581 pub require_request_uri_registration: Option<bool>,
586
587 pub require_signed_request_object: Option<bool>,
594
595 pub pushed_authorization_request_endpoint: Option<Url>,
600
601 pub require_pushed_authorization_requests: Option<bool>,
606
607 pub prompt_values_supported: Option<Vec<Prompt>>,
614
615 pub device_authorization_endpoint: Option<Url>,
619
620 pub end_session_endpoint: Option<Url>,
624
625 pub account_management_uri: Option<Url>,
630
631 pub account_management_actions_supported: Option<Vec<AccountManagementAction>>,
635}
636
637impl ProviderMetadata {
638 pub fn validate(
652 self,
653 issuer: &str,
654 ) -> Result<VerifiedProviderMetadata, ProviderMetadataVerificationError> {
655 let metadata = self.insecure_verify_metadata()?;
656
657 if metadata.issuer() != issuer {
658 return Err(ProviderMetadataVerificationError::IssuerUrlsDontMatch);
659 }
660
661 validate_url(
662 "issuer",
663 &metadata
664 .issuer()
665 .parse()
666 .map_err(|_| ProviderMetadataVerificationError::IssuerNotUrl)?,
667 ExtraUrlRestrictions::NoQueryOrFragment,
668 )?;
669
670 validate_url(
671 "authorization_endpoint",
672 metadata.authorization_endpoint(),
673 ExtraUrlRestrictions::NoFragment,
674 )?;
675
676 validate_url(
677 "token_endpoint",
678 metadata.token_endpoint(),
679 ExtraUrlRestrictions::NoFragment,
680 )?;
681
682 validate_url("jwks_uri", metadata.jwks_uri(), ExtraUrlRestrictions::None)?;
683
684 if let Some(url) = &metadata.registration_endpoint {
685 validate_url("registration_endpoint", url, ExtraUrlRestrictions::None)?;
686 }
687
688 if let Some(scopes) = &metadata.scopes_supported {
689 if !scopes.iter().any(|s| s == "openid") {
690 return Err(ProviderMetadataVerificationError::ScopesMissingOpenid);
691 }
692 }
693
694 validate_signing_alg_values_supported(
695 "token_endpoint",
696 metadata
697 .token_endpoint_auth_signing_alg_values_supported
698 .iter()
699 .flatten(),
700 metadata
701 .token_endpoint_auth_methods_supported
702 .iter()
703 .flatten(),
704 )?;
705
706 if let Some(url) = &metadata.revocation_endpoint {
707 validate_url("revocation_endpoint", url, ExtraUrlRestrictions::NoFragment)?;
708 }
709
710 validate_signing_alg_values_supported(
711 "revocation_endpoint",
712 metadata
713 .revocation_endpoint_auth_signing_alg_values_supported
714 .iter()
715 .flatten(),
716 metadata
717 .revocation_endpoint_auth_methods_supported
718 .iter()
719 .flatten(),
720 )?;
721
722 if let Some(url) = &metadata.introspection_endpoint {
723 validate_url("introspection_endpoint", url, ExtraUrlRestrictions::None)?;
724 }
725
726 let introspection_methods = metadata
729 .introspection_endpoint_auth_methods_supported
730 .as_ref()
731 .map(|v| {
732 v.iter()
733 .filter_map(AuthenticationMethodOrAccessTokenType::authentication_method)
734 .collect::<Vec<_>>()
735 });
736 validate_signing_alg_values_supported(
737 "introspection_endpoint",
738 metadata
739 .introspection_endpoint_auth_signing_alg_values_supported
740 .iter()
741 .flatten(),
742 introspection_methods.into_iter().flatten(),
743 )?;
744
745 if let Some(url) = &metadata.userinfo_endpoint {
746 validate_url("userinfo_endpoint", url, ExtraUrlRestrictions::None)?;
747 }
748
749 if let Some(url) = &metadata.pushed_authorization_request_endpoint {
750 validate_url(
751 "pushed_authorization_request_endpoint",
752 url,
753 ExtraUrlRestrictions::None,
754 )?;
755 }
756
757 if let Some(url) = &metadata.end_session_endpoint {
758 validate_url("end_session_endpoint", url, ExtraUrlRestrictions::None)?;
759 }
760
761 Ok(metadata)
762 }
763
764 pub fn insecure_verify_metadata(
786 self,
787 ) -> Result<VerifiedProviderMetadata, ProviderMetadataVerificationError> {
788 self.issuer
789 .as_ref()
790 .ok_or(ProviderMetadataVerificationError::MissingIssuer)?;
791
792 self.authorization_endpoint
793 .as_ref()
794 .ok_or(ProviderMetadataVerificationError::MissingAuthorizationEndpoint)?;
795
796 self.token_endpoint
797 .as_ref()
798 .ok_or(ProviderMetadataVerificationError::MissingTokenEndpoint)?;
799
800 self.jwks_uri
801 .as_ref()
802 .ok_or(ProviderMetadataVerificationError::MissingJwksUri)?;
803
804 self.response_types_supported
805 .as_ref()
806 .ok_or(ProviderMetadataVerificationError::MissingResponseTypesSupported)?;
807
808 self.subject_types_supported
809 .as_ref()
810 .ok_or(ProviderMetadataVerificationError::MissingSubjectTypesSupported)?;
811
812 self.id_token_signing_alg_values_supported
813 .as_ref()
814 .ok_or(ProviderMetadataVerificationError::MissingIdTokenSigningAlgValuesSupported)?;
815
816 Ok(VerifiedProviderMetadata { inner: self })
817 }
818
819 #[must_use]
824 pub fn response_modes_supported(&self) -> &[ResponseMode] {
825 self.response_modes_supported
826 .as_deref()
827 .unwrap_or(DEFAULT_RESPONSE_MODES_SUPPORTED)
828 }
829
830 #[must_use]
835 pub fn grant_types_supported(&self) -> &[GrantType] {
836 self.grant_types_supported
837 .as_deref()
838 .unwrap_or(DEFAULT_GRANT_TYPES_SUPPORTED)
839 }
840
841 #[must_use]
846 pub fn token_endpoint_auth_methods_supported(&self) -> &[OAuthClientAuthenticationMethod] {
847 self.token_endpoint_auth_methods_supported
848 .as_deref()
849 .unwrap_or(DEFAULT_AUTH_METHODS_SUPPORTED)
850 }
851
852 #[must_use]
857 pub fn revocation_endpoint_auth_methods_supported(&self) -> &[OAuthClientAuthenticationMethod] {
858 self.revocation_endpoint_auth_methods_supported
859 .as_deref()
860 .unwrap_or(DEFAULT_AUTH_METHODS_SUPPORTED)
861 }
862
863 #[must_use]
868 pub fn claim_types_supported(&self) -> &[ClaimType] {
869 self.claim_types_supported
870 .as_deref()
871 .unwrap_or(DEFAULT_CLAIM_TYPES_SUPPORTED)
872 }
873
874 #[must_use]
879 pub fn claims_parameter_supported(&self) -> bool {
880 self.claims_parameter_supported.unwrap_or(false)
881 }
882
883 #[must_use]
888 pub fn request_parameter_supported(&self) -> bool {
889 self.request_parameter_supported.unwrap_or(false)
890 }
891
892 #[must_use]
897 pub fn request_uri_parameter_supported(&self) -> bool {
898 self.request_uri_parameter_supported.unwrap_or(true)
899 }
900
901 #[must_use]
906 pub fn require_request_uri_registration(&self) -> bool {
907 self.require_request_uri_registration.unwrap_or(false)
908 }
909
910 #[must_use]
915 pub fn require_signed_request_object(&self) -> bool {
916 self.require_signed_request_object.unwrap_or(false)
917 }
918
919 #[must_use]
924 pub fn require_pushed_authorization_requests(&self) -> bool {
925 self.require_pushed_authorization_requests.unwrap_or(false)
926 }
927}
928
929#[derive(Debug, Clone)]
964pub struct VerifiedProviderMetadata {
965 inner: ProviderMetadata,
966}
967
968impl VerifiedProviderMetadata {
969 #[must_use]
971 pub fn issuer(&self) -> &str {
972 match &self.issuer {
973 Some(u) => u,
974 None => unreachable!(),
975 }
976 }
977
978 #[must_use]
980 pub fn authorization_endpoint(&self) -> &Url {
981 match &self.authorization_endpoint {
982 Some(u) => u,
983 None => unreachable!(),
984 }
985 }
986
987 #[must_use]
989 pub fn token_endpoint(&self) -> &Url {
990 match &self.token_endpoint {
991 Some(u) => u,
992 None => unreachable!(),
993 }
994 }
995
996 #[must_use]
998 pub fn jwks_uri(&self) -> &Url {
999 match &self.jwks_uri {
1000 Some(u) => u,
1001 None => unreachable!(),
1002 }
1003 }
1004
1005 #[must_use]
1008 pub fn response_types_supported(&self) -> &[ResponseType] {
1009 match &self.response_types_supported {
1010 Some(u) => u,
1011 None => unreachable!(),
1012 }
1013 }
1014
1015 #[must_use]
1018 pub fn subject_types_supported(&self) -> &[SubjectType] {
1019 match &self.subject_types_supported {
1020 Some(u) => u,
1021 None => unreachable!(),
1022 }
1023 }
1024
1025 #[must_use]
1028 pub fn id_token_signing_alg_values_supported(&self) -> &[JsonWebSignatureAlg] {
1029 match &self.id_token_signing_alg_values_supported {
1030 Some(u) => u,
1031 None => unreachable!(),
1032 }
1033 }
1034}
1035
1036impl Deref for VerifiedProviderMetadata {
1037 type Target = ProviderMetadata;
1038
1039 fn deref(&self) -> &Self::Target {
1040 &self.inner
1041 }
1042}
1043
1044#[derive(Debug, Error)]
1046pub enum ProviderMetadataVerificationError {
1047 #[error("issuer is missing")]
1049 MissingIssuer,
1050
1051 #[error("issuer is not a valid URL")]
1053 IssuerNotUrl,
1054
1055 #[error("authorization endpoint is missing")]
1057 MissingAuthorizationEndpoint,
1058
1059 #[error("token endpoint is missing")]
1061 MissingTokenEndpoint,
1062
1063 #[error("JWK Set URI is missing")]
1065 MissingJwksUri,
1066
1067 #[error("supported response types are missing")]
1069 MissingResponseTypesSupported,
1070
1071 #[error("supported subject types are missing")]
1073 MissingSubjectTypesSupported,
1074
1075 #[error("supported ID token signing algorithm values are missing")]
1077 MissingIdTokenSigningAlgValuesSupported,
1078
1079 #[error("{0}'s URL doesn't use a https scheme: {1}")]
1081 UrlNonHttpsScheme(&'static str, Url),
1082
1083 #[error("{0}'s URL contains a query: {1}")]
1085 UrlWithQuery(&'static str, Url),
1086
1087 #[error("{0}'s URL contains a fragment: {1}")]
1089 UrlWithFragment(&'static str, Url),
1090
1091 #[error("issuer URLs don't match")]
1093 IssuerUrlsDontMatch,
1094
1095 #[error("missing openid scope")]
1097 ScopesMissingOpenid,
1098
1099 #[error("missing `code` response type")]
1101 ResponseTypesMissingCode,
1102
1103 #[error("missing `id_token` response type")]
1105 ResponseTypesMissingIdToken,
1106
1107 #[error("missing `id_token token` response type")]
1109 ResponseTypesMissingIdTokenToken,
1110
1111 #[error("missing `authorization_code` grant type")]
1113 GrantTypesMissingAuthorizationCode,
1114
1115 #[error("missing `implicit` grant type")]
1117 GrantTypesMissingImplicit,
1118
1119 #[error("{0} missing auth signing algorithm values")]
1123 MissingAuthSigningAlgValues(&'static str),
1124
1125 #[error("{0} signing algorithm values contain `none`")]
1128 SigningAlgValuesWithNone(&'static str),
1129}
1130
1131#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1133enum ExtraUrlRestrictions {
1134 None,
1136
1137 NoFragment,
1139
1140 NoQueryOrFragment,
1142}
1143
1144impl ExtraUrlRestrictions {
1145 fn can_have_fragment(self) -> bool {
1146 self == Self::None
1147 }
1148
1149 fn can_have_query(self) -> bool {
1150 self != Self::NoQueryOrFragment
1151 }
1152}
1153
1154fn validate_url(
1158 field: &'static str,
1159 url: &Url,
1160 restrictions: ExtraUrlRestrictions,
1161) -> Result<(), ProviderMetadataVerificationError> {
1162 if url.scheme() != "https" {
1163 return Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(
1164 field,
1165 url.clone(),
1166 ));
1167 }
1168
1169 if !restrictions.can_have_query() && url.query().is_some() {
1170 return Err(ProviderMetadataVerificationError::UrlWithQuery(
1171 field,
1172 url.clone(),
1173 ));
1174 }
1175
1176 if !restrictions.can_have_fragment() && url.fragment().is_some() {
1177 return Err(ProviderMetadataVerificationError::UrlWithFragment(
1178 field,
1179 url.clone(),
1180 ));
1181 }
1182
1183 Ok(())
1184}
1185
1186fn validate_signing_alg_values_supported<'a>(
1194 endpoint: &'static str,
1195 values: impl Iterator<Item = &'a JsonWebSignatureAlg>,
1196 mut methods: impl Iterator<Item = &'a OAuthClientAuthenticationMethod>,
1197) -> Result<(), ProviderMetadataVerificationError> {
1198 let mut no_values = true;
1199
1200 for value in values {
1201 if *value == JsonWebSignatureAlg::None {
1202 return Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(
1203 endpoint,
1204 ));
1205 }
1206
1207 no_values = false;
1208 }
1209
1210 if no_values
1211 && methods.any(|method| {
1212 matches!(
1213 method,
1214 OAuthClientAuthenticationMethod::ClientSecretJwt
1215 | OAuthClientAuthenticationMethod::PrivateKeyJwt
1216 )
1217 })
1218 {
1219 return Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint));
1220 }
1221
1222 Ok(())
1223}
1224
1225#[skip_serializing_none]
1229#[serde_as]
1230#[derive(Default, Serialize, Deserialize, Clone)]
1231pub struct RpInitiatedLogoutRequest {
1232 pub id_token_hint: Option<String>,
1237
1238 pub logout_hint: Option<String>,
1245
1246 pub client_id: Option<String>,
1255
1256 pub post_logout_redirect_uri: Option<Url>,
1262
1263 pub state: Option<String>,
1267
1268 #[serde_as(as = "Option<StringWithSeparator::<SpaceSeparator, LanguageTag>>")]
1271 #[serde(default)]
1272 pub ui_locales: Option<Vec<LanguageTag>>,
1273}
1274
1275impl fmt::Debug for RpInitiatedLogoutRequest {
1276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1277 f.debug_struct("RpInitiatedLogoutRequest")
1278 .field("logout_hint", &self.logout_hint)
1279 .field("post_logout_redirect_uri", &self.post_logout_redirect_uri)
1280 .field("ui_locales", &self.ui_locales)
1281 .finish_non_exhaustive()
1282 }
1283}
1284
1285#[cfg(test)]
1286mod tests {
1287 use assert_matches::assert_matches;
1288 use mas_iana::{
1289 jose::JsonWebSignatureAlg,
1290 oauth::{OAuthAuthorizationEndpointResponseType, OAuthClientAuthenticationMethod},
1291 };
1292 use url::Url;
1293
1294 use super::*;
1295
1296 fn valid_provider_metadata() -> (ProviderMetadata, String) {
1297 let issuer = "https://localhost".to_owned();
1298 let metadata = ProviderMetadata {
1299 issuer: Some(issuer.clone()),
1300 authorization_endpoint: Some(Url::parse("https://localhost/auth").unwrap()),
1301 token_endpoint: Some(Url::parse("https://localhost/token").unwrap()),
1302 jwks_uri: Some(Url::parse("https://localhost/jwks").unwrap()),
1303 response_types_supported: Some(vec![
1304 OAuthAuthorizationEndpointResponseType::Code.into()
1305 ]),
1306 subject_types_supported: Some(vec![SubjectType::Public]),
1307 id_token_signing_alg_values_supported: Some(vec![JsonWebSignatureAlg::Rs256]),
1308 ..Default::default()
1309 };
1310
1311 (metadata, issuer)
1312 }
1313
1314 #[test]
1315 fn validate_required_metadata() {
1316 let (metadata, issuer) = valid_provider_metadata();
1317 metadata.validate(&issuer).unwrap();
1318 }
1319
1320 #[test]
1321 fn validate_issuer() {
1322 let (mut metadata, issuer) = valid_provider_metadata();
1323
1324 metadata.issuer = None;
1326 assert_matches!(
1327 metadata.clone().validate(&issuer),
1328 Err(ProviderMetadataVerificationError::MissingIssuer)
1329 );
1330
1331 metadata.issuer = Some("not-an-url".to_owned());
1333 assert_matches!(
1334 metadata.clone().validate("not-an-url"),
1335 Err(ProviderMetadataVerificationError::IssuerNotUrl)
1336 );
1337
1338 metadata.issuer = Some("https://example.com/".to_owned());
1340 assert_matches!(
1341 metadata.clone().validate(&issuer),
1342 Err(ProviderMetadataVerificationError::IssuerUrlsDontMatch)
1343 );
1344
1345 let issuer = "http://localhost/".to_owned();
1347 metadata.issuer = Some(issuer.clone());
1348 let (field, url) = assert_matches!(
1349 metadata.clone().validate(&issuer),
1350 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1351 );
1352 assert_eq!(field, "issuer");
1353 assert_eq!(url.as_str(), issuer);
1354
1355 let issuer = "https://localhost/?query".to_owned();
1357 metadata.issuer = Some(issuer.clone());
1358 let (field, url) = assert_matches!(
1359 metadata.clone().validate(&issuer),
1360 Err(ProviderMetadataVerificationError::UrlWithQuery(field, url)) => (field, url)
1361 );
1362 assert_eq!(field, "issuer");
1363 assert_eq!(url.as_str(), issuer);
1364
1365 let issuer = "https://localhost/#fragment".to_owned();
1367 metadata.issuer = Some(issuer.clone());
1368 let (field, url) = assert_matches!(
1369 metadata.clone().validate(&issuer),
1370 Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1371 );
1372 assert_eq!(field, "issuer");
1373 assert_eq!(url.as_str(), issuer);
1374
1375 let issuer = "https://localhost/issuer1".to_owned();
1377 metadata.issuer = Some(issuer.clone());
1378 metadata.validate(&issuer).unwrap();
1379 }
1380
1381 #[test]
1382 fn validate_authorization_endpoint() {
1383 let (mut metadata, issuer) = valid_provider_metadata();
1384
1385 metadata.authorization_endpoint = None;
1387 assert_matches!(
1388 metadata.clone().validate(&issuer),
1389 Err(ProviderMetadataVerificationError::MissingAuthorizationEndpoint)
1390 );
1391
1392 let endpoint = Url::parse("http://localhost/auth").unwrap();
1394 metadata.authorization_endpoint = Some(endpoint.clone());
1395 let (field, url) = assert_matches!(
1396 metadata.clone().validate(&issuer),
1397 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1398 );
1399 assert_eq!(field, "authorization_endpoint");
1400 assert_eq!(url, endpoint);
1401
1402 let endpoint = Url::parse("https://localhost/auth#fragment").unwrap();
1404 metadata.authorization_endpoint = Some(endpoint.clone());
1405 let (field, url) = assert_matches!(
1406 metadata.clone().validate(&issuer),
1407 Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1408 );
1409 assert_eq!(field, "authorization_endpoint");
1410 assert_eq!(url, endpoint);
1411
1412 metadata.authorization_endpoint = Some(Url::parse("https://localhost/auth?query").unwrap());
1414 metadata.validate(&issuer).unwrap();
1415 }
1416
1417 #[test]
1418 fn validate_token_endpoint() {
1419 let (mut metadata, issuer) = valid_provider_metadata();
1420
1421 metadata.token_endpoint = None;
1423 assert_matches!(
1424 metadata.clone().validate(&issuer),
1425 Err(ProviderMetadataVerificationError::MissingTokenEndpoint)
1426 );
1427
1428 let endpoint = Url::parse("http://localhost/token").unwrap();
1430 metadata.token_endpoint = Some(endpoint.clone());
1431 let (field, url) = assert_matches!(
1432 metadata.clone().validate(&issuer),
1433 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1434 );
1435 assert_eq!(field, "token_endpoint");
1436 assert_eq!(url, endpoint);
1437
1438 let endpoint = Url::parse("https://localhost/token#fragment").unwrap();
1440 metadata.token_endpoint = Some(endpoint.clone());
1441 let (field, url) = assert_matches!(
1442 metadata.clone().validate(&issuer),
1443 Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1444 );
1445 assert_eq!(field, "token_endpoint");
1446 assert_eq!(url, endpoint);
1447
1448 metadata.token_endpoint = Some(Url::parse("https://localhost/token?query").unwrap());
1450 metadata.validate(&issuer).unwrap();
1451 }
1452
1453 #[test]
1454 fn validate_jwks_uri() {
1455 let (mut metadata, issuer) = valid_provider_metadata();
1456
1457 metadata.jwks_uri = None;
1459 assert_matches!(
1460 metadata.clone().validate(&issuer),
1461 Err(ProviderMetadataVerificationError::MissingJwksUri)
1462 );
1463
1464 let endpoint = Url::parse("http://localhost/jwks").unwrap();
1466 metadata.jwks_uri = Some(endpoint.clone());
1467 let (field, url) = assert_matches!(
1468 metadata.clone().validate(&issuer),
1469 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1470 );
1471 assert_eq!(field, "jwks_uri");
1472 assert_eq!(url, endpoint);
1473
1474 metadata.jwks_uri = Some(Url::parse("https://localhost/token?query#fragment").unwrap());
1476 metadata.validate(&issuer).unwrap();
1477 }
1478
1479 #[test]
1480 fn validate_registration_endpoint() {
1481 let (mut metadata, issuer) = valid_provider_metadata();
1482
1483 let endpoint = Url::parse("http://localhost/registration").unwrap();
1485 metadata.registration_endpoint = Some(endpoint.clone());
1486 let (field, url) = assert_matches!(
1487 metadata.clone().validate(&issuer),
1488 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1489 );
1490 assert_eq!(field, "registration_endpoint");
1491 assert_eq!(url, endpoint);
1492
1493 metadata.registration_endpoint = None;
1495 metadata.clone().validate(&issuer).unwrap();
1496
1497 metadata.registration_endpoint =
1499 Some(Url::parse("https://localhost/registration?query#fragment").unwrap());
1500 metadata.validate(&issuer).unwrap();
1501 }
1502
1503 #[test]
1504 fn validate_scopes_supported() {
1505 let (mut metadata, issuer) = valid_provider_metadata();
1506
1507 metadata.scopes_supported = Some(vec!["custom".to_owned()]);
1509 assert_matches!(
1510 metadata.clone().validate(&issuer),
1511 Err(ProviderMetadataVerificationError::ScopesMissingOpenid)
1512 );
1513
1514 metadata.scopes_supported = None;
1516 metadata.clone().validate(&issuer).unwrap();
1517
1518 metadata.scopes_supported = Some(vec!["openid".to_owned(), "custom".to_owned()]);
1520 metadata.validate(&issuer).unwrap();
1521 }
1522
1523 #[test]
1524 fn validate_response_types_supported() {
1525 let (mut metadata, issuer) = valid_provider_metadata();
1526
1527 metadata.response_types_supported = None;
1529 assert_matches!(
1530 metadata.clone().validate(&issuer),
1531 Err(ProviderMetadataVerificationError::MissingResponseTypesSupported)
1532 );
1533
1534 metadata.response_types_supported =
1536 Some(vec![OAuthAuthorizationEndpointResponseType::Code.into()]);
1537 metadata.validate(&issuer).unwrap();
1538 }
1539
1540 #[test]
1541 fn validate_token_endpoint_signing_alg_values_supported() {
1542 let (mut metadata, issuer) = valid_provider_metadata();
1543
1544 metadata.token_endpoint_auth_signing_alg_values_supported = None;
1546 metadata.token_endpoint_auth_methods_supported = None;
1547 metadata.clone().validate(&issuer).unwrap();
1548
1549 metadata.token_endpoint_auth_signing_alg_values_supported =
1551 Some(vec![JsonWebSignatureAlg::None]);
1552 let endpoint = assert_matches!(
1553 metadata.clone().validate(&issuer),
1554 Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(endpoint)) => endpoint
1555 );
1556 assert_eq!(endpoint, "token_endpoint");
1557
1558 metadata.token_endpoint_auth_signing_alg_values_supported =
1560 Some(vec![JsonWebSignatureAlg::Rs256, JsonWebSignatureAlg::EdDsa]);
1561 metadata.clone().validate(&issuer).unwrap();
1562
1563 metadata.token_endpoint_auth_methods_supported =
1565 Some(vec![OAuthClientAuthenticationMethod::ClientSecretJwt]);
1566 metadata.token_endpoint_auth_signing_alg_values_supported = None;
1567 let endpoint = assert_matches!(
1568 metadata.clone().validate(&issuer),
1569 Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint)) => endpoint
1570 );
1571 assert_eq!(endpoint, "token_endpoint");
1572
1573 metadata.token_endpoint_auth_signing_alg_values_supported =
1575 Some(vec![JsonWebSignatureAlg::Rs256]);
1576 metadata.clone().validate(&issuer).unwrap();
1577
1578 metadata.token_endpoint_auth_methods_supported =
1580 Some(vec![OAuthClientAuthenticationMethod::PrivateKeyJwt]);
1581 metadata.token_endpoint_auth_signing_alg_values_supported = None;
1582 let endpoint = assert_matches!(
1583 metadata.clone().validate(&issuer),
1584 Err(ProviderMetadataVerificationError::MissingAuthSigningAlgValues(endpoint)) => endpoint
1585 );
1586 assert_eq!(endpoint, "token_endpoint");
1587
1588 metadata.token_endpoint_auth_signing_alg_values_supported =
1590 Some(vec![JsonWebSignatureAlg::Rs256]);
1591 metadata.clone().validate(&issuer).unwrap();
1592
1593 metadata.token_endpoint_auth_methods_supported = Some(vec![
1595 OAuthClientAuthenticationMethod::ClientSecretBasic,
1596 OAuthClientAuthenticationMethod::ClientSecretPost,
1597 ]);
1598 metadata.token_endpoint_auth_signing_alg_values_supported = None;
1599 metadata.validate(&issuer).unwrap();
1600 }
1601
1602 #[test]
1603 fn validate_revocation_endpoint() {
1604 let (mut metadata, issuer) = valid_provider_metadata();
1605
1606 metadata.revocation_endpoint = None;
1608 metadata.clone().validate(&issuer).unwrap();
1609
1610 let endpoint = Url::parse("http://localhost/revocation").unwrap();
1612 metadata.revocation_endpoint = Some(endpoint.clone());
1613 let (field, url) = assert_matches!(
1614 metadata.clone().validate(&issuer),
1615 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1616 );
1617 assert_eq!(field, "revocation_endpoint");
1618 assert_eq!(url, endpoint);
1619
1620 let endpoint = Url::parse("https://localhost/revocation#fragment").unwrap();
1622 metadata.revocation_endpoint = Some(endpoint.clone());
1623 let (field, url) = assert_matches!(
1624 metadata.clone().validate(&issuer),
1625 Err(ProviderMetadataVerificationError::UrlWithFragment(field, url)) => (field, url)
1626 );
1627 assert_eq!(field, "revocation_endpoint");
1628 assert_eq!(url, endpoint);
1629
1630 metadata.revocation_endpoint =
1632 Some(Url::parse("https://localhost/revocation?query").unwrap());
1633 metadata.validate(&issuer).unwrap();
1634 }
1635
1636 #[test]
1637 fn validate_revocation_endpoint_signing_alg_values_supported() {
1638 let (mut metadata, issuer) = valid_provider_metadata();
1639
1640 metadata.revocation_endpoint_auth_signing_alg_values_supported = None;
1645 metadata.revocation_endpoint_auth_methods_supported = None;
1646 metadata.clone().validate(&issuer).unwrap();
1647
1648 metadata.revocation_endpoint_auth_signing_alg_values_supported =
1650 Some(vec![JsonWebSignatureAlg::None]);
1651 let endpoint = assert_matches!(
1652 metadata.validate(&issuer),
1653 Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(endpoint)) => endpoint
1654 );
1655 assert_eq!(endpoint, "revocation_endpoint");
1656 }
1657
1658 #[test]
1659 fn validate_introspection_endpoint() {
1660 let (mut metadata, issuer) = valid_provider_metadata();
1661
1662 metadata.introspection_endpoint = None;
1664 metadata.clone().validate(&issuer).unwrap();
1665
1666 let endpoint = Url::parse("http://localhost/introspection").unwrap();
1668 metadata.introspection_endpoint = Some(endpoint.clone());
1669 let (field, url) = assert_matches!(
1670 metadata.clone().validate(&issuer),
1671 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1672 );
1673 assert_eq!(field, "introspection_endpoint");
1674 assert_eq!(url, endpoint);
1675
1676 metadata.introspection_endpoint =
1678 Some(Url::parse("https://localhost/introspection?query#fragment").unwrap());
1679 metadata.validate(&issuer).unwrap();
1680 }
1681
1682 #[test]
1683 fn validate_introspection_endpoint_signing_alg_values_supported() {
1684 let (mut metadata, issuer) = valid_provider_metadata();
1685
1686 metadata.introspection_endpoint_auth_signing_alg_values_supported = None;
1691 metadata.introspection_endpoint_auth_methods_supported = None;
1692 metadata.clone().validate(&issuer).unwrap();
1693
1694 metadata.introspection_endpoint_auth_signing_alg_values_supported =
1696 Some(vec![JsonWebSignatureAlg::None]);
1697 let endpoint = assert_matches!(
1698 metadata.validate(&issuer),
1699 Err(ProviderMetadataVerificationError::SigningAlgValuesWithNone(endpoint)) => endpoint
1700 );
1701 assert_eq!(endpoint, "introspection_endpoint");
1702 }
1703
1704 #[test]
1705 fn validate_userinfo_endpoint() {
1706 let (mut metadata, issuer) = valid_provider_metadata();
1707
1708 metadata.userinfo_endpoint = None;
1710 metadata.clone().validate(&issuer).unwrap();
1711
1712 let endpoint = Url::parse("http://localhost/userinfo").unwrap();
1714 metadata.userinfo_endpoint = Some(endpoint.clone());
1715 let (field, url) = assert_matches!(
1716 metadata.clone().validate(&issuer),
1717 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1718 );
1719 assert_eq!(field, "userinfo_endpoint");
1720 assert_eq!(url, endpoint);
1721
1722 metadata.userinfo_endpoint =
1724 Some(Url::parse("https://localhost/userinfo?query#fragment").unwrap());
1725 metadata.validate(&issuer).unwrap();
1726 }
1727
1728 #[test]
1729 fn validate_subject_types_supported() {
1730 let (mut metadata, issuer) = valid_provider_metadata();
1731
1732 metadata.subject_types_supported = None;
1734 assert_matches!(
1735 metadata.clone().validate(&issuer),
1736 Err(ProviderMetadataVerificationError::MissingSubjectTypesSupported)
1737 );
1738
1739 metadata.subject_types_supported = Some(vec![SubjectType::Public, SubjectType::Pairwise]);
1741 metadata.validate(&issuer).unwrap();
1742 }
1743
1744 #[test]
1745 fn validate_id_token_signing_alg_values_supported() {
1746 let (mut metadata, issuer) = valid_provider_metadata();
1747
1748 metadata.id_token_signing_alg_values_supported = None;
1750 assert_matches!(
1751 metadata.clone().validate(&issuer),
1752 Err(ProviderMetadataVerificationError::MissingIdTokenSigningAlgValuesSupported)
1753 );
1754
1755 metadata.id_token_signing_alg_values_supported =
1757 Some(vec![JsonWebSignatureAlg::Rs256, JsonWebSignatureAlg::EdDsa]);
1758 metadata.validate(&issuer).unwrap();
1759 }
1760
1761 #[test]
1762 fn validate_pushed_authorization_request_endpoint() {
1763 let (mut metadata, issuer) = valid_provider_metadata();
1764
1765 metadata.pushed_authorization_request_endpoint = None;
1767 metadata.clone().validate(&issuer).unwrap();
1768
1769 let endpoint = Url::parse("http://localhost/par").unwrap();
1771 metadata.pushed_authorization_request_endpoint = Some(endpoint.clone());
1772 let (field, url) = assert_matches!(
1773 metadata.clone().validate(&issuer),
1774 Err(ProviderMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1775 );
1776 assert_eq!(field, "pushed_authorization_request_endpoint");
1777 assert_eq!(url, endpoint);
1778
1779 metadata.pushed_authorization_request_endpoint =
1781 Some(Url::parse("https://localhost/par?query#fragment").unwrap());
1782 metadata.validate(&issuer).unwrap();
1783 }
1784
1785 #[test]
1786 fn serialize_application_type() {
1787 assert_eq!(
1788 serde_json::to_string(&ApplicationType::Web).unwrap(),
1789 "\"web\""
1790 );
1791 assert_eq!(
1792 serde_json::to_string(&ApplicationType::Native).unwrap(),
1793 "\"native\""
1794 );
1795 }
1796
1797 #[test]
1798 fn deserialize_application_type() {
1799 assert_eq!(
1800 serde_json::from_str::<ApplicationType>("\"web\"").unwrap(),
1801 ApplicationType::Web
1802 );
1803 assert_eq!(
1804 serde_json::from_str::<ApplicationType>("\"native\"").unwrap(),
1805 ApplicationType::Native
1806 );
1807 }
1808
1809 #[test]
1810 fn serialize_subject_type() {
1811 assert_eq!(
1812 serde_json::to_string(&SubjectType::Public).unwrap(),
1813 "\"public\""
1814 );
1815 assert_eq!(
1816 serde_json::to_string(&SubjectType::Pairwise).unwrap(),
1817 "\"pairwise\""
1818 );
1819 }
1820
1821 #[test]
1822 fn deserialize_subject_type() {
1823 assert_eq!(
1824 serde_json::from_str::<SubjectType>("\"public\"").unwrap(),
1825 SubjectType::Public
1826 );
1827 assert_eq!(
1828 serde_json::from_str::<SubjectType>("\"pairwise\"").unwrap(),
1829 SubjectType::Pairwise
1830 );
1831 }
1832
1833 #[test]
1834 fn serialize_claim_type() {
1835 assert_eq!(
1836 serde_json::to_string(&ClaimType::Normal).unwrap(),
1837 "\"normal\""
1838 );
1839 assert_eq!(
1840 serde_json::to_string(&ClaimType::Aggregated).unwrap(),
1841 "\"aggregated\""
1842 );
1843 assert_eq!(
1844 serde_json::to_string(&ClaimType::Distributed).unwrap(),
1845 "\"distributed\""
1846 );
1847 }
1848
1849 #[test]
1850 fn deserialize_claim_type() {
1851 assert_eq!(
1852 serde_json::from_str::<ClaimType>("\"normal\"").unwrap(),
1853 ClaimType::Normal
1854 );
1855 assert_eq!(
1856 serde_json::from_str::<ClaimType>("\"aggregated\"").unwrap(),
1857 ClaimType::Aggregated
1858 );
1859 assert_eq!(
1860 serde_json::from_str::<ClaimType>("\"distributed\"").unwrap(),
1861 ClaimType::Distributed
1862 );
1863 }
1864
1865 #[test]
1866 fn deserialize_auth_method_or_token_type_type() {
1867 assert_eq!(
1868 serde_json::from_str::<AuthenticationMethodOrAccessTokenType>("\"none\"").unwrap(),
1869 AuthenticationMethodOrAccessTokenType::AuthenticationMethod(
1870 OAuthClientAuthenticationMethod::None
1871 )
1872 );
1873 assert_eq!(
1874 serde_json::from_str::<AuthenticationMethodOrAccessTokenType>("\"Bearer\"").unwrap(),
1875 AuthenticationMethodOrAccessTokenType::AccessTokenType(OAuthAccessTokenType::Bearer)
1876 );
1877 assert_eq!(
1878 serde_json::from_str::<AuthenticationMethodOrAccessTokenType>("\"unknown_value\"")
1879 .unwrap(),
1880 AuthenticationMethodOrAccessTokenType::Unknown("unknown_value".to_owned())
1881 );
1882 }
1883}