identity_credential/validator/jpt_presentation_validation/
jpt_presentation_validator_utils.rs1use std::str::FromStr;
5
6use identity_core::common::Object;
7use identity_core::common::Timestamp;
8use identity_core::convert::FromJson;
9use identity_core::convert::ToJson;
10use identity_did::DID;
11use jsonprooftoken::encoding::SerializationType;
12use jsonprooftoken::jpt::claims::JptClaims;
13use jsonprooftoken::jwp::presented::JwpPresentedDecoder;
14
15use crate::credential::Credential;
16use crate::credential::CredentialJwtClaims;
17use crate::credential::Jpt;
18use crate::revocation::RevocationTimeframeStatus;
19use crate::revocation::VerifierRevocationTimeframeStatus;
20use crate::validator::JptCredentialValidatorUtils;
21use crate::validator::JwtValidationError;
22use crate::validator::SignerContext;
23
24#[derive(Debug)]
26#[non_exhaustive]
27pub struct JptPresentationValidatorUtils;
28
29type ValidationUnitResult<T = ()> = std::result::Result<T, JwtValidationError>;
30
31impl JptPresentationValidatorUtils {
32 pub fn extract_issuer_from_presented_jpt<D>(presentation: &Jpt) -> std::result::Result<D, JwtValidationError>
38 where
39 D: DID,
40 <D as FromStr>::Err: std::error::Error + Send + Sync + 'static,
41 {
42 let decoded = JwpPresentedDecoder::decode(presentation.as_str(), SerializationType::COMPACT)
43 .map_err(JwtValidationError::JwpDecodingError)?;
44 let claims = decoded
45 .get_issuer_header()
46 .claims()
47 .ok_or("Claims not present")
48 .map_err(|err| {
49 JwtValidationError::CredentialStructure(crate::Error::JptClaimsSetDeserializationError(err.into()))
50 })?;
51 let payloads = decoded.get_payloads();
52 let jpt_claims = JptClaims::from_claims_and_payloads(claims, payloads);
53 let jpt_claims_json = jpt_claims.to_json_vec().map_err(|err| {
54 JwtValidationError::CredentialStructure(crate::Error::JptClaimsSetDeserializationError(err.into()))
55 })?;
56
57 let credential_claims: CredentialJwtClaims<'_, Object> = CredentialJwtClaims::from_json_slice(&jpt_claims_json)
59 .map_err(|err| {
60 JwtValidationError::CredentialStructure(crate::Error::JwtClaimsSetDeserializationError(err.into()))
61 })?;
62
63 D::from_str(credential_claims.iss.url().as_str()).map_err(|err| JwtValidationError::SignerUrl {
64 signer_ctx: SignerContext::Issuer,
65 source: err.into(),
66 })
67 }
68
69 pub fn check_timeframes_with_validity_timeframe_2024<T>(
71 credential: &Credential<T>,
72 validity_timeframe: Option<Timestamp>,
73 status_check: crate::validator::StatusCheck,
74 ) -> ValidationUnitResult {
75 if status_check == crate::validator::StatusCheck::SkipAll {
76 return Ok(());
77 }
78
79 match &credential.credential_status {
80 None => Ok(()),
81 Some(status) => {
82 if status.type_ == RevocationTimeframeStatus::TYPE {
83 let status: VerifierRevocationTimeframeStatus =
84 VerifierRevocationTimeframeStatus::try_from(status.clone()).map_err(JwtValidationError::InvalidStatus)?;
85
86 JptCredentialValidatorUtils::check_validity_timeframe(status.0, validity_timeframe)
87 } else {
88 if status_check == crate::validator::StatusCheck::SkipUnsupported {
89 return Ok(());
90 }
91 Err(JwtValidationError::InvalidStatus(crate::Error::InvalidStatus(format!(
92 "unsupported type '{}'",
93 status.type_
94 ))))
95 }
96 }
97 }
98 }
99}