identity_credential/validator/jwt_presentation_validation/
jwt_presentation_validator_utils.rs

1// Copyright 2020-2023 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use identity_core::common::Object;
5use identity_core::convert::FromJson;
6use identity_did::DID;
7use identity_verification::jws::Decoder;
8use serde_json::Value;
9use std::str::FromStr;
10
11use crate::credential::Jwt;
12use crate::presentation::JwtPresentationV2Claims;
13use crate::presentation::Presentation;
14use crate::presentation::PresentationJwtClaims;
15use crate::validator::jwt_credential_validation::JwtValidationError;
16use crate::validator::jwt_credential_validation::SignerContext;
17
18/// Utility functions for verifying JWT presentations.
19#[non_exhaustive]
20pub struct JwtPresentationValidatorUtils;
21
22impl JwtPresentationValidatorUtils {
23  /// Attempt to extract the holder of the presentation.
24  ///
25  /// # Errors:
26  /// * If deserialization/decoding of the presentation fails.
27  /// * If the holder can't be parsed as DIDs.
28  pub fn extract_holder<H: DID>(presentation: &Jwt) -> std::result::Result<H, JwtValidationError>
29  where
30    <H as FromStr>::Err: std::error::Error + Send + Sync + 'static,
31  {
32    let validation_item = Decoder::new()
33      .decode_compact_serialization(presentation.as_str().as_bytes(), None)
34      .map_err(JwtValidationError::JwsDecodingError)?;
35
36    // Try V1 first.
37    let maybe_holder =
38      if let Ok(claims) = PresentationJwtClaims::<Value, Object>::from_json_slice(&validation_item.claims()) {
39        H::from_str(claims.iss.as_str())
40      } else if let Ok(claims) = JwtPresentationV2Claims::<Value, Object>::from_json_slice(&validation_item.claims()) {
41        H::from_str(claims.vp.holder.as_str())
42      } else {
43        return Err(JwtValidationError::PresentationStructure(
44          crate::error::Error::JwtClaimsSetDeserializationError(
45            "Failed to deserialize JWT presentation claims to either a v1 or v2 Verifiable Presentation".into(),
46          ),
47        ));
48      };
49
50    maybe_holder.map_err(|err| JwtValidationError::SignerUrl {
51      signer_ctx: SignerContext::Holder,
52      source: err.into(),
53    })
54  }
55
56  /// Validates the semantic structure of the `Presentation`.
57  pub fn check_structure<U>(presentation: &Presentation<U>) -> Result<(), JwtValidationError> {
58    presentation
59      .check_structure()
60      .map_err(JwtValidationError::PresentationStructure)
61  }
62}