From dccffeaa46e877e7822062b90a2c88b6d599026b Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Thu, 14 Sep 2023 22:19:50 +0200 Subject: [PATCH 1/2] fix holder claim check --- .../src/presentation/jwt_serialization.rs | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/identity_credential/src/presentation/jwt_serialization.rs b/identity_credential/src/presentation/jwt_serialization.rs index 5122edc420..35c41fbec4 100644 --- a/identity_credential/src/presentation/jwt_serialization.rs +++ b/identity_credential/src/presentation/jwt_serialization.rs @@ -86,6 +86,7 @@ where terms_of_use: Cow::Borrowed(terms_of_use), properties: Cow::Borrowed(properties), proof: proof.as_ref().map(Cow::Borrowed), + holder: None, }, exp: options.expiration_date.map(|expiration_date| expiration_date.to_unix()), issuance_date: options.issuance_date.map(IssuanceDateClaims::new), @@ -113,6 +114,9 @@ where /// Credential(s) expressing the claims of the `Presentation`. #[serde(default = "Default::default", rename = "verifiableCredential")] pub(crate) verifiable_credential: Cow<'presentation, Vec>, + /// The entity that generated the `Presentation`. + #[serde(skip_serializing_if = "Option::is_none")] + holder: Option, /// Service(s) used to refresh an expired [`Credential`] in the `Presentation`. #[serde(default, rename = "refreshService", skip_serializing_if = "OneOrMany::is_empty")] refresh_service: Cow<'presentation, OneOrMany>, @@ -152,6 +156,7 @@ where terms_of_use, properties, proof, + holder: _, } = vp; let presentation = Presentation { @@ -179,6 +184,182 @@ where { return Err(Error::InconsistentPresentationJwtClaims("inconsistent presentation id")); }; + + if !self + .vp + .holder + .as_ref() + .map(|value| self.iss.as_ref() == value) + .unwrap_or(true) + { + return Err(Error::InconsistentPresentationJwtClaims( + "inconsistent presentation holder", + )); + }; + Ok(()) } } + +#[cfg(test)] +mod test { + use super::PresentationJwtClaims; + use crate::{ + credential::Jwt, + presentation::{JwtPresentationOptions, Presentation}, + Error, + }; + use identity_core::{ + common::{Object, Timestamp}, + convert::{FromJson, ToJson}, + }; + + #[test] + fn roundtrip() { + let presentation_json: &str = r#" + { + "id": "http://example.edu/presentations/3732", + "@context": "https://www.w3.org/2018/credentials/v1", + "type": "VerifiablePresentation", + "verifiableCredential": [ + "eyJraWQiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjI3NzQkJ6dGpDekhzanRac2xXZmJadWszeGJQOHQwU2JTIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjIiwibmJmIjoxNjk0Njk1MTM1LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTp0c3Q6MHg2YTU4YWExMmFmY2ZhNjk4YTViZjU5OTE4MzY5YzBhYTM5OTU1ZjFhZTVhN2U1MTZiYzZiZDRkYzI3MTJkNmM3IiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJHUEEiOiI0LjAiLCJkZWdyZWUiOnsibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMiLCJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUifSwibmFtZSI6IkFsaWNlIn19fQ.ADYZEltOt2S5j2z_lnfo1GK69zUI8ndgS4CWORZT_IUuNZ9PZPzhVXaXvJ07X8iYHa7I63urKXWZnzrmMQ7UBA" + ], + "holder": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7" + } + "#; + let claims_json: &str = r#" + { + "jti": "http://example.edu/presentations/3732", + "exp": 1694699551, + "iss": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7", + "nbf": 1694698951, + "vp": { + "@context": "https://www.w3.org/2018/credentials/v1", + "type": "VerifiablePresentation", + "verifiableCredential": [ + "eyJraWQiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjI3NzQkJ6dGpDekhzanRac2xXZmJadWszeGJQOHQwU2JTIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjIiwibmJmIjoxNjk0Njk1MTM1LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTp0c3Q6MHg2YTU4YWExMmFmY2ZhNjk4YTViZjU5OTE4MzY5YzBhYTM5OTU1ZjFhZTVhN2U1MTZiYzZiZDRkYzI3MTJkNmM3IiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJHUEEiOiI0LjAiLCJkZWdyZWUiOnsibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMiLCJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUifSwibmFtZSI6IkFsaWNlIn19fQ.ADYZEltOt2S5j2z_lnfo1GK69zUI8ndgS4CWORZT_IUuNZ9PZPzhVXaXvJ07X8iYHa7I63urKXWZnzrmMQ7UBA" + ] + } + } + "#; + + let presentation: Presentation = Presentation::from_json(presentation_json).unwrap(); + let options = JwtPresentationOptions { + expiration_date: Some(Timestamp::from_unix(1694699551).unwrap()), + issuance_date: Some(Timestamp::from_unix(1694698951).unwrap()), + audience: None, + }; + let claims: PresentationJwtClaims<'_, Jwt> = + PresentationJwtClaims::<'_, Jwt>::new(&presentation, &options).unwrap(); + let claims_serialized: String = claims.to_json().unwrap(); + assert_eq!( + Object::from_json(&claims_serialized).unwrap(), + Object::from_json(claims_json).unwrap() + ); + let retrieved_presentaiton: Presentation = PresentationJwtClaims::<'_, Jwt>::from_json(&claims_serialized) + .unwrap() + .try_into_presentation() + .unwrap(); + + assert_eq!(presentation, retrieved_presentaiton); + } + + #[test] + fn claim_duplication() { + let presentation_json: &str = r#" + { + "id": "http://example.edu/presentations/3732", + "@context": "https://www.w3.org/2018/credentials/v1", + "type": "VerifiablePresentation", + "verifiableCredential": [ + "eyJraWQiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjI3NzQkJ6dGpDekhzanRac2xXZmJadWszeGJQOHQwU2JTIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjIiwibmJmIjoxNjk0Njk1MTM1LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTp0c3Q6MHg2YTU4YWExMmFmY2ZhNjk4YTViZjU5OTE4MzY5YzBhYTM5OTU1ZjFhZTVhN2U1MTZiYzZiZDRkYzI3MTJkNmM3IiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJHUEEiOiI0LjAiLCJkZWdyZWUiOnsibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMiLCJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUifSwibmFtZSI6IkFsaWNlIn19fQ.ADYZEltOt2S5j2z_lnfo1GK69zUI8ndgS4CWORZT_IUuNZ9PZPzhVXaXvJ07X8iYHa7I63urKXWZnzrmMQ7UBA" + ], + "holder": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7" + } + "#; + let claims_json: &str = r#" + { + "jti": "http://example.edu/presentations/3732", + "exp": 1694699551, + "iss": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7", + "nbf": 1694698951, + "vp": { + "id": "http://example.edu/presentations/3732", + "holder": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7", + "@context": "https://www.w3.org/2018/credentials/v1", + "type": "VerifiablePresentation", + "verifiableCredential": [ + "eyJraWQiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjI3NzQkJ6dGpDekhzanRac2xXZmJadWszeGJQOHQwU2JTIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjIiwibmJmIjoxNjk0Njk1MTM1LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTp0c3Q6MHg2YTU4YWExMmFmY2ZhNjk4YTViZjU5OTE4MzY5YzBhYTM5OTU1ZjFhZTVhN2U1MTZiYzZiZDRkYzI3MTJkNmM3IiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJHUEEiOiI0LjAiLCJkZWdyZWUiOnsibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMiLCJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUifSwibmFtZSI6IkFsaWNlIn19fQ.ADYZEltOt2S5j2z_lnfo1GK69zUI8ndgS4CWORZT_IUuNZ9PZPzhVXaXvJ07X8iYHa7I63urKXWZnzrmMQ7UBA" + ] + } + } + "#; + + let presentation: Presentation = Presentation::from_json(presentation_json).unwrap(); + let retrieved_presentaiton: Presentation = PresentationJwtClaims::<'_, Jwt>::from_json(&claims_json) + .unwrap() + .try_into_presentation() + .unwrap(); + + assert_eq!(presentation, retrieved_presentaiton); + } + + #[test] + fn inconsistent_holder() { + let claims_json: &str = r#" + { + "jti": "http://example.edu/presentations/3732", + "exp": 1694699551, + "iss": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7", + "nbf": 1694698951, + "vp": { + "id": "http://example.edu/presentations/3732", + "@context": "https://www.w3.org/2018/credentials/v1", + "holder": "did:iota:tst2:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7", + "type": "VerifiablePresentation", + "verifiableCredential": [ + "eyJraWQiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjI3NzQkJ6dGpDekhzanRac2xXZmJadWszeGJQOHQwU2JTIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjIiwibmJmIjoxNjk0Njk1MTM1LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTp0c3Q6MHg2YTU4YWExMmFmY2ZhNjk4YTViZjU5OTE4MzY5YzBhYTM5OTU1ZjFhZTVhN2U1MTZiYzZiZDRkYzI3MTJkNmM3IiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJHUEEiOiI0LjAiLCJkZWdyZWUiOnsibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMiLCJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUifSwibmFtZSI6IkFsaWNlIn19fQ.ADYZEltOt2S5j2z_lnfo1GK69zUI8ndgS4CWORZT_IUuNZ9PZPzhVXaXvJ07X8iYHa7I63urKXWZnzrmMQ7UBA" + ] + } + } + "#; + + let presentation_from_claims_result: Result, _> = + PresentationJwtClaims::<'_, Jwt>::from_json(claims_json) + .unwrap() + .try_into_presentation(); + assert!(matches!( + presentation_from_claims_result.unwrap_err(), + Error::InconsistentPresentationJwtClaims("inconsistent presentation holder") + )); + } + + #[test] + fn inconsistent_id() { + let claims_json: &str = r#" + { + "jti": "http://example.edu/presentations/3732", + "exp": 1694699551, + "iss": "did:iota:tst:0x6a58aa12afcfa698a5bf59918369c0aa39955f1ae5a7e516bc6bd4dc2712d6c7", + "nbf": 1694698951, + "vp": { + "id": "http://example.edu/presentations/1111", + "@context": "https://www.w3.org/2018/credentials/v1", + "type": "VerifiablePresentation", + "verifiableCredential": [ + "eyJraWQiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjI3NzQkJ6dGpDekhzanRac2xXZmJadWszeGJQOHQwU2JTIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6aW90YTp0c3Q6MHgxOTg0NjdmNWUzNGQwYjNkMTA3MjRhYjY3NDNhZDQxNTdjNjdjYjJiYjNhNjU2ODYzYmY2YzBjMGFmMmM3ODJjIiwibmJmIjoxNjk0Njk1MTM1LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTp0c3Q6MHg2YTU4YWExMmFmY2ZhNjk4YTViZjU5OTE4MzY5YzBhYTM5OTU1ZjFhZTVhN2U1MTZiYzZiZDRkYzI3MTJkNmM3IiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJHUEEiOiI0LjAiLCJkZWdyZWUiOnsibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMiLCJ0eXBlIjoiQmFjaGVsb3JEZWdyZWUifSwibmFtZSI6IkFsaWNlIn19fQ.ADYZEltOt2S5j2z_lnfo1GK69zUI8ndgS4CWORZT_IUuNZ9PZPzhVXaXvJ07X8iYHa7I63urKXWZnzrmMQ7UBA" + ] + } + } + "#; + + let presentation_from_claims_result: Result, _> = + PresentationJwtClaims::<'_, Jwt>::from_json(claims_json) + .unwrap() + .try_into_presentation(); + assert!(matches!( + presentation_from_claims_result.unwrap_err(), + Error::InconsistentPresentationJwtClaims("inconsistent presentation id") + )); + } +} From 40b2f6a2bc2dbe6ad91b59a34c967af0d52c5c52 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Thu, 14 Sep 2023 22:20:09 +0200 Subject: [PATCH 2/2] fmt --- .../src/presentation/jwt_serialization.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/identity_credential/src/presentation/jwt_serialization.rs b/identity_credential/src/presentation/jwt_serialization.rs index 35c41fbec4..dbe9491d22 100644 --- a/identity_credential/src/presentation/jwt_serialization.rs +++ b/identity_credential/src/presentation/jwt_serialization.rs @@ -204,15 +204,14 @@ where #[cfg(test)] mod test { use super::PresentationJwtClaims; - use crate::{ - credential::Jwt, - presentation::{JwtPresentationOptions, Presentation}, - Error, - }; - use identity_core::{ - common::{Object, Timestamp}, - convert::{FromJson, ToJson}, - }; + use crate::credential::Jwt; + use crate::presentation::JwtPresentationOptions; + use crate::presentation::Presentation; + use crate::Error; + use identity_core::common::Object; + use identity_core::common::Timestamp; + use identity_core::convert::FromJson; + use identity_core::convert::ToJson; #[test] fn roundtrip() {