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    pub fn validate(self) -> Result<VerifiedClientMetadata, ClientMetadataVerificationError> {
444        let grant_types = self.grant_types();
445        let has_implicit = grant_types.contains(&GrantType::Implicit);
446        let has_authorization_code = grant_types.contains(&GrantType::AuthorizationCode);
447        let has_both = has_implicit && has_authorization_code;
448
449        if let Some(uris) = &self.redirect_uris {
450            if let Some(uri) = uris.iter().find(|uri| uri.fragment().is_some()) {
451                return Err(ClientMetadataVerificationError::RedirectUriWithFragment(
452                    uri.clone(),
453                ));
454            }
455        } else if has_authorization_code || has_implicit {
456            return Err(ClientMetadataVerificationError::MissingRedirectUris);
458        }
459
460        let response_type_code = [OAuthAuthorizationEndpointResponseType::Code.into()];
461        let response_types = match &self.response_types {
462            Some(types) => &types[..],
463            None if has_authorization_code || has_implicit => &response_type_code[..],
465            None => &[],
466        };
467
468        for response_type in response_types {
469            let has_code = response_type.has_code();
470            let has_id_token = response_type.has_id_token();
471            let has_token = response_type.has_token();
472            let is_ok = has_code && has_both
473                || !has_code && has_implicit
474                || has_authorization_code && !has_id_token && !has_token
475                || !has_code && !has_id_token && !has_token;
476
477            if !is_ok {
478                return Err(ClientMetadataVerificationError::IncoherentResponseType(
479                    response_type.clone(),
480                ));
481            }
482        }
483
484        if self.jwks_uri.is_some() && self.jwks.is_some() {
485            return Err(ClientMetadataVerificationError::JwksUriAndJwksMutuallyExclusive);
486        }
487
488        if let Some(url) = self
489            .sector_identifier_uri
490            .as_ref()
491            .filter(|url| url.scheme() != "https")
492        {
493            return Err(ClientMetadataVerificationError::UrlNonHttpsScheme(
494                "sector_identifier_uri",
495                url.clone(),
496            ));
497        }
498
499        if *self.token_endpoint_auth_method() == OAuthClientAuthenticationMethod::PrivateKeyJwt
500            && self.jwks_uri.is_none()
501            && self.jwks.is_none()
502        {
503            return Err(ClientMetadataVerificationError::MissingJwksForTokenMethod);
504        }
505
506        if let Some(alg) = &self.token_endpoint_auth_signing_alg {
507            if *alg == JsonWebSignatureAlg::None {
508                return Err(ClientMetadataVerificationError::UnauthorizedSigningAlgNone(
509                    "token_endpoint",
510                ));
511            }
512        } else if matches!(
513            self.token_endpoint_auth_method(),
514            OAuthClientAuthenticationMethod::PrivateKeyJwt
515                | OAuthClientAuthenticationMethod::ClientSecretJwt
516        ) {
517            return Err(ClientMetadataVerificationError::MissingAuthSigningAlg(
518                "token_endpoint",
519            ));
520        }
521
522        if *self.id_token_signed_response_alg() == JsonWebSignatureAlg::None
523            && response_types.iter().any(ResponseType::has_id_token)
524        {
525            return Err(ClientMetadataVerificationError::IdTokenSigningAlgNone);
526        }
527
528        if self.id_token_encrypted_response_enc.is_some() {
529            self.id_token_encrypted_response_alg.as_ref().ok_or(
530                ClientMetadataVerificationError::MissingEncryptionAlg("id_token"),
531            )?;
532        }
533
534        if self.userinfo_encrypted_response_enc.is_some() {
535            self.userinfo_encrypted_response_alg.as_ref().ok_or(
536                ClientMetadataVerificationError::MissingEncryptionAlg("userinfo"),
537            )?;
538        }
539
540        if self.request_object_encryption_enc.is_some() {
541            self.request_object_encryption_alg.as_ref().ok_or(
542                ClientMetadataVerificationError::MissingEncryptionAlg("request_object"),
543            )?;
544        }
545
546        if let Some(url) = self
547            .initiate_login_uri
548            .as_ref()
549            .filter(|url| url.scheme() != "https")
550        {
551            return Err(ClientMetadataVerificationError::UrlNonHttpsScheme(
552                "initiate_login_uri",
553                url.clone(),
554            ));
555        }
556
557        if self.introspection_encrypted_response_enc.is_some() {
558            self.introspection_encrypted_response_alg.as_ref().ok_or(
559                ClientMetadataVerificationError::MissingEncryptionAlg("introspection"),
560            )?;
561        }
562
563        Ok(VerifiedClientMetadata { inner: self })
564    }
565
566    #[must_use]
569    pub fn sorted(mut self) -> Self {
570        if let Some(redirect_uris) = &mut self.redirect_uris {
572            redirect_uris.sort();
573        }
574        if let Some(response_types) = &mut self.response_types {
575            response_types.sort();
576        }
577        if let Some(grant_types) = &mut self.grant_types {
578            grant_types.sort();
579        }
580        if let Some(contacts) = &mut self.contacts {
581            contacts.sort();
582        }
583        if let Some(client_name) = &mut self.client_name {
584            client_name.sort();
585        }
586        if let Some(logo_uri) = &mut self.logo_uri {
587            logo_uri.sort();
588        }
589        if let Some(client_uri) = &mut self.client_uri {
590            client_uri.sort();
591        }
592        if let Some(policy_uri) = &mut self.policy_uri {
593            policy_uri.sort();
594        }
595        if let Some(tos_uri) = &mut self.tos_uri {
596            tos_uri.sort();
597        }
598        if let Some(default_acr_values) = &mut self.default_acr_values {
599            default_acr_values.sort();
600        }
601        if let Some(request_uris) = &mut self.request_uris {
602            request_uris.sort();
603        }
604        if let Some(post_logout_redirect_uris) = &mut self.post_logout_redirect_uris {
605            post_logout_redirect_uris.sort();
606        }
607
608        self
609    }
610
611    #[must_use]
622    pub fn response_types(&self) -> Vec<ResponseType> {
623        self.response_types.clone().unwrap_or_else(|| {
624            DEFAULT_RESPONSE_TYPES
625                .into_iter()
626                .map(ResponseType::from)
627                .collect()
628        })
629    }
630
631    #[must_use]
644    pub fn grant_types(&self) -> &[GrantType] {
645        self.grant_types.as_deref().unwrap_or(DEFAULT_GRANT_TYPES)
646    }
647
648    #[must_use]
652    pub fn application_type(&self) -> ApplicationType {
653        self.application_type
654            .clone()
655            .unwrap_or(DEFAULT_APPLICATION_TYPE)
656    }
657
658    #[must_use]
664    pub fn token_endpoint_auth_method(&self) -> &OAuthClientAuthenticationMethod {
665        self.token_endpoint_auth_method
666            .as_ref()
667            .unwrap_or(DEFAULT_TOKEN_AUTH_METHOD)
668    }
669
670    #[must_use]
681    pub fn id_token_signed_response_alg(&self) -> &JsonWebSignatureAlg {
682        self.id_token_signed_response_alg
683            .as_ref()
684            .unwrap_or(DEFAULT_SIGNING_ALGORITHM)
685    }
686
687    #[must_use]
696    pub fn id_token_encrypted_response(
697        &self,
698    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
699        self.id_token_encrypted_response_alg.as_ref().map(|alg| {
700            (
701                alg,
702                self.id_token_encrypted_response_enc
703                    .as_ref()
704                    .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
705            )
706        })
707    }
708
709    #[must_use]
718    pub fn userinfo_encrypted_response(
719        &self,
720    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
721        self.userinfo_encrypted_response_alg.as_ref().map(|alg| {
722            (
723                alg,
724                self.userinfo_encrypted_response_enc
725                    .as_ref()
726                    .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
727            )
728        })
729    }
730
731    #[must_use]
740    pub fn request_object_encryption(
741        &self,
742    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
743        self.request_object_encryption_alg.as_ref().map(|alg| {
744            (
745                alg,
746                self.request_object_encryption_enc
747                    .as_ref()
748                    .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
749            )
750        })
751    }
752
753    #[must_use]
757    pub fn require_auth_time(&self) -> bool {
758        self.require_auth_time.unwrap_or_default()
759    }
760
761    #[must_use]
768    pub fn require_signed_request_object(&self) -> bool {
769        self.require_signed_request_object.unwrap_or_default()
770    }
771
772    #[must_use]
779    pub fn require_pushed_authorization_requests(&self) -> bool {
780        self.require_pushed_authorization_requests
781            .unwrap_or_default()
782    }
783
784    #[must_use]
794    pub fn introspection_encrypted_response(
795        &self,
796    ) -> Option<(&JsonWebEncryptionAlg, &JsonWebEncryptionEnc)> {
797        self.introspection_encrypted_response_alg
798            .as_ref()
799            .map(|alg| {
800                (
801                    alg,
802                    self.introspection_encrypted_response_enc
803                        .as_ref()
804                        .unwrap_or(DEFAULT_ENCRYPTION_ENC_ALGORITHM),
805                )
806            })
807    }
808}
809
810#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
819#[serde(into = "ClientMetadataSerdeHelper")]
820pub struct VerifiedClientMetadata {
821    inner: ClientMetadata,
822}
823
824impl VerifiedClientMetadata {
825    #[must_use]
833    pub fn redirect_uris(&self) -> &[Url] {
834        match &self.redirect_uris {
835            Some(v) => v,
836            None => &[],
837        }
838    }
839}
840
841impl Deref for VerifiedClientMetadata {
842    type Target = ClientMetadata;
843
844    fn deref(&self) -> &Self::Target {
845        &self.inner
846    }
847}
848
849#[derive(Debug, Error)]
851pub enum ClientMetadataVerificationError {
852    #[error("redirect URIs are missing")]
854    MissingRedirectUris,
855
856    #[error("redirect URI with fragment: {0}")]
858    RedirectUriWithFragment(Url),
859
860    #[error("'{0}' response type not compatible with grant types")]
862    IncoherentResponseType(ResponseType),
863
864    #[error("jwks_uri and jwks are mutually exclusive")]
867    JwksUriAndJwksMutuallyExclusive,
868
869    #[error("{0}'s URL doesn't use a https scheme: {1}")]
871    UrlNonHttpsScheme(&'static str, Url),
872
873    #[error("missing JWK Set for token auth method")]
875    MissingJwksForTokenMethod,
876
877    #[error("none signing alg unauthorized for {0}")]
879    UnauthorizedSigningAlgNone(&'static str),
880
881    #[error("{0} missing auth signing algorithm")]
885    MissingAuthSigningAlg(&'static str),
886
887    #[error("ID Token signing alg is none")]
890    IdTokenSigningAlgNone,
891
892    #[error("{0} missing encryption alg value")]
894    MissingEncryptionAlg(&'static str),
895}
896
897#[serde_as]
899#[skip_serializing_none]
900#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
901pub struct ClientRegistrationResponse {
902    pub client_id: String,
904
905    #[serde(default)]
907    pub client_secret: Option<String>,
908
909    #[serde(default)]
911    #[serde_as(as = "Option<TimestampSeconds<i64>>")]
912    pub client_id_issued_at: Option<DateTime<Utc>>,
913
914    #[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    fn validate_response_types() {
998        let mut metadata = valid_client_metadata();
999
1000        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Code.into()]);
1003        metadata.clone().validate().unwrap();
1004
1005        let response_type: ResponseType =
1007            OAuthAuthorizationEndpointResponseType::CodeIdToken.into();
1008        metadata.response_types = Some(vec![response_type.clone()]);
1009        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1010        assert_eq!(res, response_type);
1011
1012        let response_type: ResponseType =
1014            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into();
1015        metadata.response_types = Some(vec![response_type.clone()]);
1016        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1017        assert_eq!(res, response_type);
1018
1019        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::CodeToken.into();
1021        metadata.response_types = Some(vec![response_type.clone()]);
1022        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1023        assert_eq!(res, response_type);
1024
1025        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::IdToken.into();
1027        metadata.response_types = Some(vec![response_type.clone()]);
1028        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1029        assert_eq!(res, response_type);
1030
1031        let response_type: ResponseType =
1033            OAuthAuthorizationEndpointResponseType::IdTokenToken.into();
1034        metadata.response_types = Some(vec![response_type.clone()]);
1035        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1036        assert_eq!(res, response_type);
1037
1038        let response_type: ResponseType =
1040            OAuthAuthorizationEndpointResponseType::IdTokenToken.into();
1041        metadata.response_types = Some(vec![response_type.clone()]);
1042        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1043        assert_eq!(res, response_type);
1044
1045        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1047        metadata.clone().validate().unwrap();
1048
1049        metadata.grant_types = Some(vec![GrantType::Implicit]);
1051        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::Code.into();
1053        metadata.response_types = Some(vec![response_type.clone()]);
1054        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1055        assert_eq!(res, response_type);
1056
1057        let response_type: ResponseType =
1059            OAuthAuthorizationEndpointResponseType::CodeIdToken.into();
1060        metadata.response_types = Some(vec![response_type.clone()]);
1061        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1062        assert_eq!(res, response_type);
1063
1064        let response_type: ResponseType =
1066            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into();
1067        metadata.response_types = Some(vec![response_type.clone()]);
1068        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1069        assert_eq!(res, response_type);
1070
1071        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::CodeToken.into();
1073        metadata.response_types = Some(vec![response_type.clone()]);
1074        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1075        assert_eq!(res, response_type);
1076
1077        metadata.response_types =
1079            Some(vec![OAuthAuthorizationEndpointResponseType::IdToken.into()]);
1080        metadata.clone().validate().unwrap();
1081
1082        metadata.response_types = Some(vec![
1084            OAuthAuthorizationEndpointResponseType::IdTokenToken.into(),
1085        ]);
1086        metadata.clone().validate().unwrap();
1087
1088        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Token.into()]);
1090        metadata.clone().validate().unwrap();
1091
1092        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1094        metadata.clone().validate().unwrap();
1095
1096        metadata.grant_types = Some(vec![GrantType::AuthorizationCode, GrantType::Implicit]);
1098        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Code.into()]);
1100        metadata.clone().validate().unwrap();
1101
1102        metadata.response_types = Some(vec![
1104            OAuthAuthorizationEndpointResponseType::CodeIdToken.into(),
1105        ]);
1106        metadata.clone().validate().unwrap();
1107
1108        metadata.response_types = Some(vec![
1110            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into(),
1111        ]);
1112        metadata.clone().validate().unwrap();
1113
1114        metadata.response_types = Some(vec![
1116            OAuthAuthorizationEndpointResponseType::CodeToken.into(),
1117        ]);
1118        metadata.clone().validate().unwrap();
1119
1120        metadata.response_types =
1122            Some(vec![OAuthAuthorizationEndpointResponseType::IdToken.into()]);
1123        metadata.clone().validate().unwrap();
1124
1125        metadata.response_types = Some(vec![
1127            OAuthAuthorizationEndpointResponseType::IdTokenToken.into(),
1128        ]);
1129        metadata.clone().validate().unwrap();
1130
1131        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::Token.into()]);
1133        metadata.clone().validate().unwrap();
1134
1135        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1137        metadata.clone().validate().unwrap();
1138
1139        metadata.grant_types = Some(vec![GrantType::RefreshToken, GrantType::ClientCredentials]);
1141        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::Code.into();
1143        metadata.response_types = Some(vec![response_type.clone()]);
1144        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1145        assert_eq!(res, response_type);
1146
1147        let response_type: ResponseType =
1149            OAuthAuthorizationEndpointResponseType::CodeIdToken.into();
1150        metadata.response_types = Some(vec![response_type.clone()]);
1151        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1152        assert_eq!(res, response_type);
1153
1154        let response_type: ResponseType =
1156            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into();
1157        metadata.response_types = Some(vec![response_type.clone()]);
1158        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1159        assert_eq!(res, response_type);
1160
1161        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::CodeToken.into();
1163        metadata.response_types = Some(vec![response_type.clone()]);
1164        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1165        assert_eq!(res, response_type);
1166
1167        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::IdToken.into();
1169        metadata.response_types = Some(vec![response_type.clone()]);
1170        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1171        assert_eq!(res, response_type);
1172
1173        let response_type: ResponseType =
1175            OAuthAuthorizationEndpointResponseType::IdTokenToken.into();
1176        metadata.response_types = Some(vec![response_type.clone()]);
1177        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1178        assert_eq!(res, response_type);
1179
1180        let response_type: ResponseType = OAuthAuthorizationEndpointResponseType::Token.into();
1182        metadata.response_types = Some(vec![response_type.clone()]);
1183        let res = assert_matches!(metadata.clone().validate(), Err(ClientMetadataVerificationError::IncoherentResponseType(res)) => res);
1184        assert_eq!(res, response_type);
1185
1186        metadata.response_types = Some(vec![OAuthAuthorizationEndpointResponseType::None.into()]);
1188        metadata.validate().unwrap();
1189    }
1190
1191    #[test]
1192    fn validate_jwks() {
1193        let mut metadata = valid_client_metadata();
1194
1195        metadata.jwks_uri = Some(Url::parse("http://localhost/jwks").unwrap());
1197        metadata.clone().validate().unwrap();
1198
1199        metadata.jwks = Some(jwks());
1201        assert_matches!(
1202            metadata.clone().validate(),
1203            Err(ClientMetadataVerificationError::JwksUriAndJwksMutuallyExclusive)
1204        );
1205
1206        metadata.jwks_uri = None;
1208        metadata.validate().unwrap();
1209    }
1210
1211    #[test]
1212    fn validate_sector_identifier_uri() {
1213        let mut metadata = valid_client_metadata();
1214
1215        let identifier_uri = Url::parse("http://localhost/").unwrap();
1217        metadata.sector_identifier_uri = Some(identifier_uri.clone());
1218        let (field, url) = assert_matches!(
1219            metadata.clone().validate(),
1220            Err(ClientMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1221        );
1222        assert_eq!(field, "sector_identifier_uri");
1223        assert_eq!(url, identifier_uri);
1224
1225        metadata.sector_identifier_uri = Some(Url::parse("https://localhost/").unwrap());
1227        metadata.validate().unwrap();
1228    }
1229
1230    #[test]
1231    fn validate_token_endpoint_auth_method() {
1232        let mut metadata = valid_client_metadata();
1233
1234        metadata.token_endpoint_auth_signing_alg = Some(JsonWebSignatureAlg::None);
1236        let field = assert_matches!(
1237            metadata.clone().validate(),
1238            Err(ClientMetadataVerificationError::UnauthorizedSigningAlgNone(field)) => field
1239        );
1240        assert_eq!(field, "token_endpoint");
1241
1242        metadata.token_endpoint_auth_method = Some(OAuthClientAuthenticationMethod::PrivateKeyJwt);
1244        metadata.token_endpoint_auth_signing_alg = Some(JsonWebSignatureAlg::Rs256);
1245
1246        assert_matches!(
1248            metadata.clone().validate(),
1249            Err(ClientMetadataVerificationError::MissingJwksForTokenMethod)
1250        );
1251
1252        metadata.jwks_uri = Some(Url::parse("https://localhost/jwks").unwrap());
1254        metadata.clone().validate().unwrap();
1255
1256        metadata.jwks_uri = None;
1258        metadata.jwks = Some(jwks());
1259        metadata.clone().validate().unwrap();
1260
1261        metadata.token_endpoint_auth_signing_alg = None;
1263        let field = assert_matches!(
1264            metadata.clone().validate(),
1265            Err(ClientMetadataVerificationError::MissingAuthSigningAlg(field)) => field
1266        );
1267        assert_eq!(field, "token_endpoint");
1268
1269        metadata.token_endpoint_auth_method =
1271            Some(OAuthClientAuthenticationMethod::ClientSecretJwt);
1272        metadata.jwks = None;
1273
1274        let field = assert_matches!(
1276            metadata.clone().validate(),
1277            Err(ClientMetadataVerificationError::MissingAuthSigningAlg(field)) => field
1278        );
1279        assert_eq!(field, "token_endpoint");
1280
1281        metadata.token_endpoint_auth_signing_alg = Some(JsonWebSignatureAlg::Rs256);
1283        metadata.validate().unwrap();
1284    }
1285
1286    #[test]
1287    fn validate_id_token_signed_response_alg() {
1288        let mut metadata = valid_client_metadata();
1289        metadata.id_token_signed_response_alg = Some(JsonWebSignatureAlg::None);
1290        metadata.grant_types = Some(vec![GrantType::AuthorizationCode, GrantType::Implicit]);
1291
1292        metadata.response_types = Some(vec![
1294            OAuthAuthorizationEndpointResponseType::CodeIdToken.into(),
1295        ]);
1296        assert_matches!(
1297            metadata.clone().validate(),
1298            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1299        );
1300
1301        metadata.response_types = Some(vec![
1303            OAuthAuthorizationEndpointResponseType::CodeIdTokenToken.into(),
1304        ]);
1305        assert_matches!(
1306            metadata.clone().validate(),
1307            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1308        );
1309
1310        metadata.response_types =
1312            Some(vec![OAuthAuthorizationEndpointResponseType::IdToken.into()]);
1313        assert_matches!(
1314            metadata.clone().validate(),
1315            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1316        );
1317
1318        metadata.response_types = Some(vec![
1320            OAuthAuthorizationEndpointResponseType::IdTokenToken.into(),
1321        ]);
1322        assert_matches!(
1323            metadata.clone().validate(),
1324            Err(ClientMetadataVerificationError::IdTokenSigningAlgNone)
1325        );
1326
1327        metadata.response_types = Some(vec![
1329            OAuthAuthorizationEndpointResponseType::Code.into(),
1330            OAuthAuthorizationEndpointResponseType::CodeToken.into(),
1331            OAuthAuthorizationEndpointResponseType::Token.into(),
1332            OAuthAuthorizationEndpointResponseType::None.into(),
1333        ]);
1334        metadata.validate().unwrap();
1335    }
1336
1337    #[test]
1338    fn validate_id_token_encrypted_response() {
1339        let mut metadata = valid_client_metadata();
1340        metadata.id_token_encrypted_response_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1341
1342        let field = assert_matches!(
1344            metadata.clone().validate(),
1345            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1346        );
1347        assert_eq!(field, "id_token");
1348
1349        metadata.id_token_encrypted_response_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1351        metadata.validate().unwrap();
1352    }
1353
1354    #[test]
1355    fn validate_userinfo_encrypted_response() {
1356        let mut metadata = valid_client_metadata();
1357        metadata.userinfo_encrypted_response_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1358
1359        let field = assert_matches!(
1361            metadata.clone().validate(),
1362            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1363        );
1364        assert_eq!(field, "userinfo");
1365
1366        metadata.userinfo_encrypted_response_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1368        metadata.validate().unwrap();
1369    }
1370
1371    #[test]
1372    fn validate_request_object_encryption() {
1373        let mut metadata = valid_client_metadata();
1374        metadata.request_object_encryption_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1375
1376        let field = assert_matches!(
1378            metadata.clone().validate(),
1379            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1380        );
1381        assert_eq!(field, "request_object");
1382
1383        metadata.request_object_encryption_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1385        metadata.validate().unwrap();
1386    }
1387
1388    #[test]
1389    fn validate_initiate_login_uri() {
1390        let mut metadata = valid_client_metadata();
1391
1392        let initiate_uri = Url::parse("http://localhost/").unwrap();
1394        metadata.initiate_login_uri = Some(initiate_uri.clone());
1395        let (field, url) = assert_matches!(
1396            metadata.clone().validate(),
1397            Err(ClientMetadataVerificationError::UrlNonHttpsScheme(field, url)) => (field, url)
1398        );
1399        assert_eq!(field, "initiate_login_uri");
1400        assert_eq!(url, initiate_uri);
1401
1402        metadata.initiate_login_uri = Some(Url::parse("https://localhost/").unwrap());
1404        metadata.validate().unwrap();
1405    }
1406
1407    #[test]
1408    fn validate_introspection_encrypted_response() {
1409        let mut metadata = valid_client_metadata();
1410        metadata.introspection_encrypted_response_enc = Some(JsonWebEncryptionEnc::A128CbcHs256);
1411
1412        let field = assert_matches!(
1414            metadata.clone().validate(),
1415            Err(ClientMetadataVerificationError::MissingEncryptionAlg(field)) => field
1416        );
1417        assert_eq!(field, "introspection");
1418
1419        metadata.introspection_encrypted_response_alg = Some(JsonWebEncryptionAlg::RsaOaep);
1421        metadata.validate().unwrap();
1422    }
1423}