1use std::ops::Deref;
12
13use chrono::{DateTime, Duration, Utc};
14use indexmap::IndexMap;
15use language_tags::LanguageTag;
16use mas_iana::{
17    jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg},
18    oauth::{OAuthAuthorizationEndpointResponseType, OAuthClientAuthenticationMethod},
19};
20use mas_jose::jwk::PublicJsonWebKeySet;
21use serde::{Deserialize, Serialize};
22use serde_with::{TimestampSeconds, serde_as, skip_serializing_none};
23use thiserror::Error;
24use url::Url;
25
26use crate::{
27    oidc::{ApplicationType, SubjectType},
28    requests::GrantType,
29    response_type::ResponseType,
30};
31
32mod client_metadata_serde;
33use client_metadata_serde::ClientMetadataSerdeHelper;
34
35pub const DEFAULT_RESPONSE_TYPES: [OAuthAuthorizationEndpointResponseType; 1] =
37    [OAuthAuthorizationEndpointResponseType::Code];
38
39pub const DEFAULT_GRANT_TYPES: &[GrantType] = &[GrantType::AuthorizationCode];
41
42pub const DEFAULT_APPLICATION_TYPE: ApplicationType = ApplicationType::Web;
44
45pub const DEFAULT_TOKEN_AUTH_METHOD: &OAuthClientAuthenticationMethod =
47    &OAuthClientAuthenticationMethod::ClientSecretBasic;
48
49pub const DEFAULT_SIGNING_ALGORITHM: &JsonWebSignatureAlg = &JsonWebSignatureAlg::Rs256;
51
52pub const DEFAULT_ENCRYPTION_ENC_ALGORITHM: &JsonWebEncryptionEnc =
54    &JsonWebEncryptionEnc::A128CbcHs256;
55
56#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct Localized<T> {
61    non_localized: T,
62    localized: IndexMap<LanguageTag, T>,
63}
64
65impl<T> Localized<T> {
66    pub fn new(non_localized: T, localized: impl IntoIterator<Item = (LanguageTag, T)>) -> Self {
69        Self {
70            non_localized,
71            localized: localized.into_iter().collect(),
72        }
73    }
74
75    #[allow(clippy::len_without_is_empty)]
77    pub fn len(&self) -> usize {
78        self.localized.len() + 1
79    }
80
81    pub fn non_localized(&self) -> &T {
83        &self.non_localized
84    }
85
86    pub fn to_non_localized(self) -> T {
88        self.non_localized
89    }
90
91    pub fn get(&self, language: Option<&LanguageTag>) -> Option<&T> {
93        match language {
94            Some(lang) => self.localized.get(lang),
95            None => Some(&self.non_localized),
96        }
97    }
98
99    pub fn iter(&self) -> impl Iterator<Item = (Option<&LanguageTag>, &T)> {
101        Some(&self.non_localized)
102            .into_iter()
103            .map(|val| (None, val))
104            .chain(self.localized.iter().map(|(lang, val)| (Some(lang), val)))
105    }
106}
107
108impl<T> From<(T, IndexMap<LanguageTag, T>)> for Localized<T> {
109    fn from(t: (T, IndexMap<LanguageTag, T>)) -> Self {
110        Localized {
111            non_localized: t.0,
112            localized: t.1,
113        }
114    }
115}
116
117#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
123#[serde(from = "ClientMetadataSerdeHelper", into = "ClientMetadataSerdeHelper")]
124pub struct ClientMetadata {
125    pub redirect_uris: Option<Vec<Url>>,
135
136    pub response_types: Option<Vec<ResponseType>>,
147
148    pub grant_types: Option<Vec<GrantType>>,
163
164    pub application_type: Option<ApplicationType>,
168
169    pub contacts: Option<Vec<String>>,
171
172    pub client_name: Option<Localized<String>>,
174
175    pub logo_uri: Option<Localized<Url>>,
177
178    pub client_uri: Option<Localized<Url>>,
180
181    pub policy_uri: Option<Localized<Url>>,
184
185    pub tos_uri: Option<Localized<Url>>,
188
189    pub jwks_uri: Option<Url>,
200
201    pub jwks: Option<PublicJsonWebKeySet>,
210
211    pub software_id: Option<String>,
218
219    pub software_version: Option<String>,
222
223    pub sector_identifier_uri: Option<Url>,
230
231    pub subject_type: Option<SubjectType>,
235
236    pub token_endpoint_auth_method: Option<OAuthClientAuthenticationMethod>,
245
246    pub token_endpoint_auth_signing_alg: Option<JsonWebSignatureAlg>,
258
259    pub id_token_signed_response_alg: Option<JsonWebSignatureAlg>,
270
271    pub id_token_encrypted_response_alg: Option<JsonWebEncryptionAlg>,
278
279    pub id_token_encrypted_response_enc: Option<JsonWebEncryptionEnc>,
287
288    pub userinfo_signed_response_alg: Option<JsonWebSignatureAlg>,
292
293    pub userinfo_encrypted_response_alg: Option<JsonWebEncryptionAlg>,
302
303    pub userinfo_encrypted_response_enc: Option<JsonWebEncryptionEnc>,
313
314    pub request_object_signing_alg: Option<JsonWebSignatureAlg>,
321
322    pub request_object_encryption_alg: Option<JsonWebEncryptionAlg>,
329
330    pub request_object_encryption_enc: Option<JsonWebEncryptionEnc>,
338
339    pub default_max_age: Option<Duration>,
347
348    pub require_auth_time: Option<bool>,
352
353    pub default_acr_values: Option<Vec<String>>,
355
356    pub initiate_login_uri: Option<Url>,
362
363    pub request_uris: Option<Vec<Url>>,
377
378    pub require_signed_request_object: Option<bool>,
385
386    pub require_pushed_authorization_requests: Option<bool>,
393
394    pub introspection_signed_response_alg: Option<JsonWebSignatureAlg>,
400
401    pub introspection_encrypted_response_alg: Option<JsonWebEncryptionAlg>,
413
414    pub introspection_encrypted_response_enc: Option<JsonWebEncryptionEnc>,
426
427    pub post_logout_redirect_uris: Option<Vec<Url>>,
432}
433
434impl ClientMetadata {
435    #[allow(clippy::too_many_lines)]
444    pub fn validate(self) -> Result<VerifiedClientMetadata, ClientMetadataVerificationError> {
445        let grant_types = self.grant_types();
446        let has_implicit = grant_types.contains(&GrantType::Implicit);
447        let has_authorization_code = grant_types.contains(&GrantType::AuthorizationCode);
448        let has_both = has_implicit && has_authorization_code;
449
450        if let Some(uris) = &self.redirect_uris {
451            if let Some(uri) = uris.iter().find(|uri| uri.fragment().is_some()) {
452                return Err(ClientMetadataVerificationError::RedirectUriWithFragment(
453                    uri.clone(),
454                ));
455            }
456        } else if has_authorization_code || has_implicit {
457            return Err(ClientMetadataVerificationError::MissingRedirectUris);
459        }
460
461        let response_type_code = [OAuthAuthorizationEndpointResponseType::Code.into()];
462        let response_types = match &self.response_types {
463            Some(types) => &types[..],
464            None if has_authorization_code || has_implicit => &response_type_code[..],
466            None => &[],
467        };
468
469        for response_type in response_types {
470            let has_code = response_type.has_code();
471            let has_id_token = response_type.has_id_token();
472            let has_token = response_type.has_token();
473            let is_ok = has_code && has_both
474                || !has_code && has_implicit
475                || has_authorization_code && !has_id_token && !has_token
476                || !has_code && !has_id_token && !has_token;
477
478            if !is_ok {
479                return Err(ClientMetadataVerificationError::IncoherentResponseType(
480                    response_type.clone(),
481                ));
482            }
483        }
484
485        if self.jwks_uri.is_some() && self.jwks.is_some() {
486            return Err(ClientMetadataVerificationError::JwksUriAndJwksMutuallyExclusive);
487        }
488
489        if let Some(url) = self
490            .sector_identifier_uri
491            .as_ref()
492            .filter(|url| url.scheme() != "https")
493        {
494            return Err(ClientMetadataVerificationError::UrlNonHttpsScheme(
495                "sector_identifier_uri",
496                url.clone(),
497            ));
498        }
499
500        if *self.token_endpoint_auth_method() == OAuthClientAuthenticationMethod::PrivateKeyJwt
501            && self.jwks_uri.is_none()
502            && self.jwks.is_none()
503        {
504            return Err(ClientMetadataVerificationError::MissingJwksForTokenMethod);
505        }
506
507        if let Some(alg) = &self.token_endpoint_auth_signing_alg {
508            if *alg == JsonWebSignatureAlg::None {
509                return Err(ClientMetadataVerificationError::UnauthorizedSigningAlgNone(
510                    "token_endpoint",
511                ));
512            }
513        } else if matches!(
514            self.token_endpoint_auth_method(),
515            OAuthClientAuthenticationMethod::PrivateKeyJwt
516                | OAuthClientAuthenticationMethod::ClientSecretJwt
517        ) {
518            return Err(ClientMetadataVerificationError::MissingAuthSigningAlg(
519                "token_endpoint",
520            ));
521        }
522
523        if *self.id_token_signed_response_alg() == JsonWebSignatureAlg::None
524            && response_types.iter().any(ResponseType::has_id_token)
525        {
526            return Err(ClientMetadataVerificationError::IdTokenSigningAlgNone);
527        }
528
529        if self.id_token_encrypted_response_enc.is_some() {
530            self.id_token_encrypted_response_alg.as_ref().ok_or(
531                ClientMetadataVerificationError::MissingEncryptionAlg("id_token"),
532            )?;
533        }
534
535        if self.userinfo_encrypted_response_enc.is_some() {
536            self.userinfo_encrypted_response_alg.as_ref().ok_or(
537                ClientMetadataVerificationError::MissingEncryptionAlg("userinfo"),
538            )?;
539        }
540
541        if self.request_object_encryption_enc.is_some() {
542            self.request_object_encryption_alg.as_ref().ok_or(
543                ClientMetadataVerificationError::MissingEncryptionAlg("request_object"),
544            )?;
545        }
546
547        if let Some(url) = self
548            .initiate_login_uri
549            .as_ref()
550            .filter(|url| url.scheme() != "https")
551        {
552            return Err(ClientMetadataVerificationError::UrlNonHttpsScheme(
553                "initiate_login_uri",
554                url.clone(),
555            ));
556        }
557
558        if self.introspection_encrypted_response_enc.is_some() {
559            self.introspection_encrypted_response_alg.as_ref().ok_or(
560                ClientMetadataVerificationError::MissingEncryptionAlg("introspection"),
561            )?;
562        }
563
564        Ok(VerifiedClientMetadata { inner: self })
565    }
566
567    #[must_use]
570    pub fn sorted(mut self) -> Self {
571        if let Some(redirect_uris) = &mut self.redirect_uris {
573            redirect_uris.sort();
574        }
575        if let Some(response_types) = &mut self.response_types {
576            response_types.sort();
577        }
578        if let Some(grant_types) = &mut self.grant_types {
579            grant_types.sort();
580        }
581        if let Some(contacts) = &mut self.contacts {
582            contacts.sort();
583        }
584        if let Some(client_name) = &mut self.client_name {
585            client_name.sort();
586        }
587        if let Some(logo_uri) = &mut self.logo_uri {
588            logo_uri.sort();
589        }
590        if let Some(client_uri) = &mut self.client_uri {
591            client_uri.sort();
592        }
593        if let Some(policy_uri) = &mut self.policy_uri {
594            policy_uri.sort();
595        }
596        if let Some(tos_uri) = &mut self.tos_uri {
597            tos_uri.sort();
598        }
599        if let Some(default_acr_values) = &mut self.default_acr_values {
600            default_acr_values.sort();
601        }
602        if let Some(request_uris) = &mut self.request_uris {
603            request_uris.sort();
604        }
605        if let Some(post_logout_redirect_uris) = &mut self.post_logout_redirect_uris {
606            post_logout_redirect_uris.sort();
607        }
608
609        self
610    }
611
612    #[must_use]
623    pub fn response_types(&self) -> Vec<ResponseType> {
624        self.response_types.clone().unwrap_or_else(|| {
625            DEFAULT_RESPONSE_TYPES
626                .into_iter()
627                .map(ResponseType::from)
628                .collect()
629        })
630    }
631
632    #[must_use]
645    pub fn grant_types(&self) -> &[GrantType] {
646        self.grant_types.as_deref().unwrap_or(DEFAULT_GRANT_TYPES)
647    }
648
649    #[must_use]
653    pub fn application_type(&self) -> ApplicationType {
654        self.application_type
655            .clone()
656            .unwrap_or(DEFAULT_APPLICATION_TYPE)
657    }
658
659    #[must_use]
665    pub fn token_endpoint_auth_method(&self) -> &OAuthClientAuthenticationMethod {
666        self.token_endpoint_auth_method
667            .as_ref()
668            .unwrap_or(DEFAULT_TOKEN_AUTH_METHOD)
669    }
670
671    #[must_use]
682    pub fn id_token_signed_response_alg(&self) -> &JsonWebSignatureAlg {
683        self.id_token_signed_response_alg
684            .as_ref()
685            .unwrap_or(DEFAULT_SIGNING_ALGORITHM)
686    }
687
688    #[must_use]
697    pub fn id_token_encrypted_response(
698        &self,
699    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
700        self.id_token_encrypted_response_alg.as_ref().map(|alg| {
701            (
702                alg,
703                self.id_token_encrypted_response_enc
704                    .as_ref()
705                    .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
706            )
707        })
708    }
709
710    #[must_use]
719    pub fn userinfo_encrypted_response(
720        &self,
721    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
722        self.userinfo_encrypted_response_alg.as_ref().map(|alg| {
723            (
724                alg,
725                self.userinfo_encrypted_response_enc
726                    .as_ref()
727                    .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
728            )
729        })
730    }
731
732    #[must_use]
741    pub fn request_object_encryption(
742        &self,
743    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
744        self.request_object_encryption_alg.as_ref().map(|alg| {
745            (
746                alg,
747                self.request_object_encryption_enc
748                    .as_ref()
749                    .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
750            )
751        })
752    }
753
754    #[must_use]
758    pub fn require_auth_time(&self) -> bool {
759        self.require_auth_time.unwrap_or_default()
760    }
761
762    #[must_use]
769    pub fn require_signed_request_object(&self) -> bool {
770        self.require_signed_request_object.unwrap_or_default()
771    }
772
773    #[must_use]
780    pub fn require_pushed_authorization_requests(&self) -> bool {
781        self.require_pushed_authorization_requests
782            .unwrap_or_default()
783    }
784
785    #[must_use]
795    pub fn introspection_encrypted_response(
796        &self,
797    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
798        self.introspection_encrypted_response_alg
799            .as_ref()
800            .map(|alg| {
801                (
802                    alg,
803                    self.introspection_encrypted_response_enc
804                        .as_ref()
805                        .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
806                )
807            })
808    }
809}
810
811#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
820#[serde(into = "ClientMetadataSerdeHelper")]
821pub struct VerifiedClientMetadata {
822    inner: ClientMetadata,
823}
824
825impl VerifiedClientMetadata {
826    #[must_use]
834    pub fn redirect_uris(&self) -> &[Url] {
835        match &self.redirect_uris {
836            Some(v) => v,
837            None => &[],
838        }
839    }
840}
841
842impl Deref for VerifiedClientMetadata {
843    type Target = ClientMetadata;
844
845    fn deref(&self) -> &Self::Target {
846        &self.inner
847    }
848}
849
850#[derive(Debug, Error)]
852pub enum ClientMetadataVerificationError {
853    #[error("redirect URIs are missing")]
855    MissingRedirectUris,
856
857    #[error("redirect URI with fragment: {0}")]
859    RedirectUriWithFragment(Url),
860
861    #[error("'{0}' response type not compatible with grant types")]
863    IncoherentResponseType(ResponseType),
864
865    #[error("jwks_uri and jwks are mutually exclusive")]
868    JwksUriAndJwksMutuallyExclusive,
869
870    #[error("{0}'s URL doesn't use a https scheme: {1}")]
872    UrlNonHttpsScheme(&'static str, Url),
873
874    #[error("missing JWK Set for token auth method")]
876    MissingJwksForTokenMethod,
877
878    #[error("none signing alg unauthorized for {0}")]
880    UnauthorizedSigningAlgNone(&'static str),
881
882    #[error("{0} missing auth signing algorithm")]
886    MissingAuthSigningAlg(&'static str),
887
888    #[error("ID Token signing alg is none")]
891    IdTokenSigningAlgNone,
892
893    #[error("{0} missing encryption alg value")]
895    MissingEncryptionAlg(&'static str),
896}
897
898#[serde_as]
900#[skip_serializing_none]
901#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
902pub struct ClientRegistrationResponse {
903    pub client_id: String,
905
906    #[serde(default)]
908    pub client_secret: Option<String>,
909
910    #[serde(default)]
912    #[serde_as(as = "Option<TimestampSeconds<i64>>")]
913    pub client_id_issued_at: Option<DateTime<Utc>>,
914
915    #[serde(default)]
919    #[serde_as(as = "Option<TimestampSeconds<i64>>")]
920    pub client_secret_expires_at: Option<DateTime<Utc>>,
921}
922
923#[cfg(test)]
924mod tests {
925    use assert_matches::assert_matches;
926    use mas_iana::{
927        jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg},
928        oauth::{OAuthAuthorizationEndpointResponseType, OAuthClientAuthenticationMethod},
929    };
930    use mas_jose::jwk::PublicJsonWebKeySet;
931    use url::Url;
932
933    use super::{ClientMetadata, ClientMetadataVerificationError};
934    use crate::{requests::GrantType, response_type::ResponseType};
935
936    fn valid_client_metadata() -> ClientMetadata {
937        ClientMetadata {
938            redirect_uris: Some(vec![Url::parse("http://localhost/oidc").unwrap()]),
939            ..Default::default()
940        }
941    }
942
943    fn jwks() -> PublicJsonWebKeySet {
944        serde_json::from_value(serde_json::json!({
945            "keys": [
946                {
947                    "alg": "RS256",
948                    "kty": "RSA",
949                    "n": "tCwhHOxX_ylh5kVwfVqW7QIBTIsPjkjCjVCppDrynuF_3msEdtEaG64eJUz84ODFNMCC0BQ57G7wrKQVWkdSDxWUEqGk2BixBiHJRWZdofz1WOBTdPVicvHW5Zl_aIt7uXWMdOp_SODw-O2y2f05EqbFWFnR2-1y9K8KbiOp82CD72ny1Jbb_3PxTs2Z0F4ECAtTzpDteaJtjeeueRjr7040JAjQ-5fpL5D1g8x14LJyVIo-FL_y94NPFbMp7UCi69CIfVHXFO8WYFz949og-47mWRrID5lS4zpx-QLuvNhUb_lSqmylUdQB3HpRdOcYdj3xwy4MHJuu7tTaf0AmCQ",
950                    "use": "sig",
951                    "kid": "d98f49bc6ca4581eae8dfadd494fce10ea23aab0",
952                    "e": "AQAB"
953                }
954            ]
955        })).unwrap()
956    }
957
958    #[test]
959    fn validate_required_metadata() {
960        let metadata = valid_client_metadata();
961        metadata.validate().unwrap();
962    }
963
964    #[test]
965    fn validate_redirect_uris() {
966        let mut metadata = ClientMetadata::default();
967
968        assert_matches!(
970            metadata.clone().validate(),
971            Err(ClientMetadataVerificationError::MissingRedirectUris)
972        );
973
974        let wrong_uri = Url::parse("http://localhost/#fragment").unwrap();
976        metadata.redirect_uris = Some(vec![
977            Url::parse("http://localhost/").unwrap(),
978            wrong_uri.clone(),
979        ]);
980        let uri = assert_matches!(
981            metadata.clone().validate(),
982            Err(ClientMetadataVerificationError::RedirectUriWithFragment(uri)) => uri
983        );
984        assert_eq!(uri, wrong_uri);
985
986        metadata.redirect_uris = Some(vec![
988            Url::parse("http://localhost/").unwrap(),
989            Url::parse("http://localhost/oidc").unwrap(),
990            Url::parse("http://localhost/?oidc").unwrap(),
991            Url::parse("http://localhost/my-client?oidc").unwrap(),
992        ]);
993        metadata.validate().unwrap();
994    }
995
996    #[test]
997    #[allow(clippy::too_many_lines)]
998    fn validate_response_types() {
999        let mut metadata = valid_client_metadata();
1000
1001        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Code.into()]);
1004        metadata.clone().validate().unwrap();
1005
1006        let response_type: ResponseType =
1008            OAuthAuthorizationEndpointResponseType::CodeIdToken.into();
1009        metadata.response_types = Some(vec![response_type.clone()]);
1010        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1011        assert_eq!(res, response_type);
1012
1013        let response_type: ResponseType =
1015            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into();
1016        metadata.response_types = Some(vec![response_type.clone()]);
1017        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1018        assert_eq!(res, response_type);
1019
1020        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::CodeToken.into();
1022        metadata.response_types = Some(vec![response_type.clone()]);
1023        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1024        assert_eq!(res, response_type);
1025
1026        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::IdToken.into();
1028        metadata.response_types = Some(vec![response_type.clone()]);
1029        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1030        assert_eq!(res, response_type);
1031
1032        let response_type: ResponseType =
1034            OAuthAuthorizationEndpointResponseType::IdTokenToken.into();
1035        metadata.response_types = Some(vec![response_type.clone()]);
1036        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1037        assert_eq!(res, response_type);
1038
1039        let response_type: ResponseType =
1041            OAuthAuthorizationEndpointResponseType::IdTokenToken.into();
1042        metadata.response_types = Some(vec![response_type.clone()]);
1043        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1044        assert_eq!(res, response_type);
1045
1046        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1048        metadata.clone().validate().unwrap();
1049
1050        metadata.grant_types = Some(vec![GrantType::Implicit]);
1052        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::Code.into();
1054        metadata.response_types = Some(vec![response_type.clone()]);
1055        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1056        assert_eq!(res, response_type);
1057
1058        let response_type: ResponseType =
1060            OAuthAuthorizationEndpointResponseType::CodeIdToken.into();
1061        metadata.response_types = Some(vec![response_type.clone()]);
1062        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1063        assert_eq!(res, response_type);
1064
1065        let response_type: ResponseType =
1067            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into();
1068        metadata.response_types = Some(vec![response_type.clone()]);
1069        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1070        assert_eq!(res, response_type);
1071
1072        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::CodeToken.into();
1074        metadata.response_types = Some(vec![response_type.clone()]);
1075        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1076        assert_eq!(res, response_type);
1077
1078        metadata.response_types =
1080            Some(vec![OAuthAuthorizationEndpointResponseType::IdToken.into()]);
1081        metadata.clone().validate().unwrap();
1082
1083        metadata.response_types = Some(vec![
1085            OAuthAuthorizationEndpointResponseType::IdTokenToken.into(),
1086        ]);
1087        metadata.clone().validate().unwrap();
1088
1089        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Token.into()]);
1091        metadata.clone().validate().unwrap();
1092
1093        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1095        metadata.clone().validate().unwrap();
1096
1097        metadata.grant_types = Some(vec![GrantType::AuthorizationCode, GrantType::Implicit]);
1099        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Code.into()]);
1101        metadata.clone().validate().unwrap();
1102
1103        metadata.response_types = Some(vec![
1105            OAuthAuthorizationEndpointResponseType::CodeIdToken.into(),
1106        ]);
1107        metadata.clone().validate().unwrap();
1108
1109        metadata.response_types = Some(vec![
1111            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into(),
1112        ]);
1113        metadata.clone().validate().unwrap();
1114
1115        metadata.response_types = Some(vec![
1117            OAuthAuthorizationEndpointResponseType::CodeToken.into(),
1118        ]);
1119        metadata.clone().validate().unwrap();
1120
1121        metadata.response_types =
1123            Some(vec![OAuthAuthorizationEndpointResponseType::IdToken.into()]);
1124        metadata.clone().validate().unwrap();
1125
1126        metadata.response_types = Some(vec![
1128            OAuthAuthorizationEndpointResponseType::IdTokenToken.into(),
1129        ]);
1130        metadata.clone().validate().unwrap();
1131
1132        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Token.into()]);
1134        metadata.clone().validate().unwrap();
1135
1136        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1138        metadata.clone().validate().unwrap();
1139
1140        metadata.grant_types = Some(vec![GrantType::RefreshToken, GrantType::ClientCredentials]);
1142        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::Code.into();
1144        metadata.response_types = Some(vec![response_type.clone()]);
1145        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1146        assert_eq!(res, response_type);
1147
1148        let response_type: ResponseType =
1150            OAuthAuthorizationEndpointResponseType::CodeIdToken.into();
1151        metadata.response_types = Some(vec![response_type.clone()]);
1152        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1153        assert_eq!(res, response_type);
1154
1155        let response_type: ResponseType =
1157            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into();
1158        metadata.response_types = Some(vec![response_type.clone()]);
1159        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1160        assert_eq!(res, response_type);
1161
1162        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::CodeToken.into();
1164        metadata.response_types = Some(vec![response_type.clone()]);
1165        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1166        assert_eq!(res, response_type);
1167
1168        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::IdToken.into();
1170        metadata.response_types = Some(vec![response_type.clone()]);
1171        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1172        assert_eq!(res, response_type);
1173
1174        let response_type: ResponseType =
1176            OAuthAuthorizationEndpointResponseType::IdTokenToken.into();
1177        metadata.response_types = Some(vec![response_type.clone()]);
1178        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1179        assert_eq!(res, response_type);
1180
1181        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::Token.into();
1183        metadata.response_types = Some(vec![response_type.clone()]);
1184        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1185        assert_eq!(res, response_type);
1186
1187        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1189        metadata.validate().unwrap();
1190    }
1191
1192    #[test]
1193    fn validate_jwks() {
1194        let mut metadata = valid_client_metadata();
1195
1196        metadata.jwks_uri = Some(Url::parse("http://localhost/jwks").unwrap());
1198        metadata.clone().validate().unwrap();
1199
1200        metadata.jwks = Some(jwks());
1202        assert_matches!(
1203            metadata.clone().validate(),
1204            Err(ClientMetadataVerificationError::JwksUriAndJwksMutuallyExclusive)
1205        );
1206
1207        metadata.jwks_uri = None;
1209        metadata.validate().unwrap();
1210    }
1211
1212    #[test]
1213    fn validate_sector_identifier_uri() {
1214        let mut metadata = valid_client_metadata();
1215
1216        let identifier_uri = Url::parse("http://localhost/").unwrap();
1218        metadata.sector_identifier_uri = Some(identifier_uri.clone());
1219        let (field, url) = assert_matches!(
1220            metadata.clone().validate(),
1221            Err(ClientMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1222        );
1223        assert_eq!(field, "sector_identifier_uri");
1224        assert_eq!(url, identifier_uri);
1225
1226        metadata.sector_identifier_uri = Some(Url::parse("https://localhost/").unwrap());
1228        metadata.validate().unwrap();
1229    }
1230
1231    #[test]
1232    fn validate_token_endpoint_auth_method() {
1233        let mut metadata = valid_client_metadata();
1234
1235        metadata.token_endpoint_auth_signing_alg = Some(JsonWebSignatureAlg::None);
1237        let field = assert_matches!(
1238            metadata.clone().validate(),
1239            Err(ClientMetadataVerificationError::UnauthorizedSigningAlgNone(field)) => field
1240        );
1241        assert_eq!(field, "token_endpoint");
1242
1243        metadata.token_endpoint_auth_method = Some(OAuthClientAuthenticationMethod::PrivateKeyJwt);
1245        metadata.token_endpoint_auth_signing_alg = Some(JsonWebSignatureAlg::Rs256);
1246
1247        assert_matches!(
1249            metadata.clone().validate(),
1250            Err(ClientMetadataVerificationError::MissingJwksForTokenMethod)
1251        );
1252
1253        metadata.jwks_uri = Some(Url::parse("https://localhost/jwks").unwrap());
1255        metadata.clone().validate().unwrap();
1256
1257        metadata.jwks_uri = None;
1259        metadata.jwks = Some(jwks());
1260        metadata.clone().validate().unwrap();
1261
1262        metadata.token_endpoint_auth_signing_alg = None;
1264        let field = assert_matches!(
1265            metadata.clone().validate(),
1266            Err(ClientMetadataVerificationError::MissingAuthSigningAlg(field)) => field
1267        );
1268        assert_eq!(field, "token_endpoint");
1269
1270        metadata.token_endpoint_auth_method =
1272            Some(OAuthClientAuthenticationMethod::ClientSecretJwt);
1273        metadata.jwks = None;
1274
1275        let field = assert_matches!(
1277            metadata.clone().validate(),
1278            Err(ClientMetadataVerificationError::MissingAuthSigningAlg(field)) => field
1279        );
1280        assert_eq!(field, "token_endpoint");
1281
1282        metadata.token_endpoint_auth_signing_alg = Some(JsonWebSignatureAlg::Rs256);
1284        metadata.validate().unwrap();
1285    }
1286
1287    #[test]
1288    fn validate_id_token_signed_response_alg() {
1289        let mut metadata = valid_client_metadata();
1290        metadata.id_token_signed_response_alg = Some(JsonWebSignatureAlg::None);
1291        metadata.grant_types = Some(vec![GrantType::AuthorizationCode, GrantType::Implicit]);
1292
1293        metadata.response_types = Some(vec![
1295            OAuthAuthorizationEndpointResponseType::CodeIdToken.into(),
1296        ]);
1297        assert_matches!(
1298            metadata.clone().validate(),
1299            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1300        );
1301
1302        metadata.response_types = Some(vec![
1304            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into(),
1305        ]);
1306        assert_matches!(
1307            metadata.clone().validate(),
1308            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1309        );
1310
1311        metadata.response_types =
1313            Some(vec![OAuthAuthorizationEndpointResponseType::IdToken.into()]);
1314        assert_matches!(
1315            metadata.clone().validate(),
1316            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1317        );
1318
1319        metadata.response_types = Some(vec![
1321            OAuthAuthorizationEndpointResponseType::IdTokenToken.into(),
1322        ]);
1323        assert_matches!(
1324            metadata.clone().validate(),
1325            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1326        );
1327
1328        metadata.response_types = Some(vec![
1330            OAuthAuthorizationEndpointResponseType::Code.into(),
1331            OAuthAuthorizationEndpointResponseType::CodeToken.into(),
1332            OAuthAuthorizationEndpointResponseType::Token.into(),
1333            OAuthAuthorizationEndpointResponseType::None.into(),
1334        ]);
1335        metadata.validate().unwrap();
1336    }
1337
1338    #[test]
1339    fn validate_id_token_encrypted_response() {
1340        let mut metadata = valid_client_metadata();
1341        metadata.id_token_encrypted_response_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1342
1343        let field = assert_matches!(
1345            metadata.clone().validate(),
1346            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1347        );
1348        assert_eq!(field, "id_token");
1349
1350        metadata.id_token_encrypted_response_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1352        metadata.validate().unwrap();
1353    }
1354
1355    #[test]
1356    fn validate_userinfo_encrypted_response() {
1357        let mut metadata = valid_client_metadata();
1358        metadata.userinfo_encrypted_response_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1359
1360        let field = assert_matches!(
1362            metadata.clone().validate(),
1363            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1364        );
1365        assert_eq!(field, "userinfo");
1366
1367        metadata.userinfo_encrypted_response_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1369        metadata.validate().unwrap();
1370    }
1371
1372    #[test]
1373    fn validate_request_object_encryption() {
1374        let mut metadata = valid_client_metadata();
1375        metadata.request_object_encryption_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1376
1377        let field = assert_matches!(
1379            metadata.clone().validate(),
1380            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1381        );
1382        assert_eq!(field, "request_object");
1383
1384        metadata.request_object_encryption_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1386        metadata.validate().unwrap();
1387    }
1388
1389    #[test]
1390    fn validate_initiate_login_uri() {
1391        let mut metadata = valid_client_metadata();
1392
1393        let initiate_uri = Url::parse("http://localhost/").unwrap();
1395        metadata.initiate_login_uri = Some(initiate_uri.clone());
1396        let (field, url) = assert_matches!(
1397            metadata.clone().validate(),
1398            Err(ClientMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1399        );
1400        assert_eq!(field, "initiate_login_uri");
1401        assert_eq!(url, initiate_uri);
1402
1403        metadata.initiate_login_uri = Some(Url::parse("https://localhost/").unwrap());
1405        metadata.validate().unwrap();
1406    }
1407
1408    #[test]
1409    fn validate_introspection_encrypted_response() {
1410        let mut metadata = valid_client_metadata();
1411        metadata.introspection_encrypted_response_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1412
1413        let field = assert_matches!(
1415            metadata.clone().validate(),
1416            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1417        );
1418        assert_eq!(field, "introspection");
1419
1420        metadata.introspection_encrypted_response_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1422        metadata.validate().unwrap();
1423    }
1424}