Skip to content

Commit

Permalink
Add feature flag for maximized interoperability.
Browse files Browse the repository at this point in the history
Adds a new feature flag that permits non-critical deviations from the
specifications to enable full interoperability testing with other
vendors.
  • Loading branch information
cobward committed Jan 3, 2025
1 parent 19aa323 commit 7036303
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ documentation = "https://docs.rs/openid4vp/"

[features]
default = []
# Enables code paths that increase the chance of interoperability with other wallets and verifiers.
# This should be used with caution in production environments.
maximize_interoperability = []

[dependencies]
anyhow = "1.0.75"
Expand All @@ -20,15 +23,14 @@ http = "1.1.0"
# This is currently used in the jwt_vp test to go from a `VeriableCredential` to an `AnyJsonCredential` type.
# There may be a better way to handle this that doesn't require the `json-syntax` crate directly.
json-syntax = { version = "0.12.5", features = ["serde_json"] }
# jsonpath_lib = "0.3.0"
serde_json_path = "0.7.1"
jsonschema = "0.18.0"
openid4vp-frontend = { version = "0.1.0", path = "openid4vp-frontend" }
p256 = { version = "0.13.2", features = ["jwk"] }
rand = { version = "0.8.5" }
reqwest = { version = "0.12.5", features = ["rustls-tls"] }
serde = "1.0.188"
serde_json = "1.0.107"
serde_json_path = "0.7.1"
serde_urlencoded = "0.7.1"
ssi = { version = "0.10.1", features = ["secp256r1"] }
tokio = "1.32.0"
Expand Down
21 changes: 17 additions & 4 deletions src/core/authorization_request/verification/x509_san.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub fn validate<V: Verifier>(
let leaf_cert = Certificate::from_der(&leaf_cert_der)
.context("leaf certificate in 'x5c' was not valid DER")?;

debug!("Leaf certificate: {leaf_cert:?}");

if !leaf_cert
.tbs_certificate
.filter::<SubjectAltName>()
Expand All @@ -82,19 +84,30 @@ pub fn validate<V: Verifier>(
.flatten()
.filter_map(|gn| match (gn, x509_san_variant) {
(GeneralName::DnsName(uri), X509SanVariant::Dns) => Some(uri.to_string()),
(GeneralName::UniformResourceIdentifier(uri), X509SanVariant::Uri) => {
Some(uri.to_string())
}
#[cfg(feature = "maximize_interoperability")]
(GeneralName::DnsName(uri), X509SanVariant::Uri) => Some(uri.to_string()),
#[cfg(feature = "maximize_interoperability")]
(GeneralName::UniformResourceIdentifier(uri), X509SanVariant::Dns) => Some(
Url::parse(uri.as_str())
.map(|u| u.authority().to_string())
.unwrap_or(uri.to_string()),
),
(gn, X509SanVariant::Dns) => {
debug!("found non-DNS SAN: {gn:?}");
None
}
(GeneralName::UniformResourceIdentifier(uri), X509SanVariant::Uri) => {
Some(uri.to_string())
}
(gn, X509SanVariant::Uri) => {
debug!("found non-URI SAN: {gn:?}");
None
}
})
.any(|uri| uri == client_id)
.any(|uri| {
debug!("comparing SAN '{uri}' to client_id '{client_id}'");
uri == client_id
})
{
bail!("client_id does not match any Subject Alternative Name")
}
Expand Down
13 changes: 5 additions & 8 deletions src/core/presentation_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::collections::HashSet;

use anyhow::Result;
use serde::{Deserialize, Serialize};
use serde_json::Map;
use serde_json::{Map, Value as Json};

/// A presentation definition is a JSON object that describes the information a [Verifier](https://identity.foundation/presentation-exchange/spec/v2.0.0/#term:verifier) requires of a [Holder](https://identity.foundation/presentation-exchange/spec/v2.0.0/#term:holder).
///
Expand Down Expand Up @@ -189,10 +189,7 @@ impl PresentationDefinition {
/// Returns the requested fields of a given JSON-encoded credential
/// that match the constraint fields of the input descriptors of the
/// presentation definition.
pub fn requested_fields<'a>(
&self,
credential: &'a serde_json::Value,
) -> Vec<RequestedField<'a>> {
pub fn requested_fields<'a>(&self, credential: &'a Json) -> Vec<RequestedField<'a>> {
self.input_descriptors
.iter()
.flat_map(|descriptor| descriptor.requested_fields(credential))
Expand All @@ -215,7 +212,7 @@ impl PresentationDefinition {
/// NOTE: this method accepts a generic serde_json::Value argument and checks whether
/// the JSON value conforms to the presentation definition's input descriptor constraint
/// fields.
pub fn is_credential_match(&self, credential: &serde_json::Value) -> bool {
pub fn is_credential_match(&self, credential: &Json) -> bool {
self.input_descriptors()
.iter()
.flat_map(|descriptor| descriptor.constraints.fields())
Expand All @@ -228,7 +225,7 @@ impl PresentationDefinition {
.iter()
.flat_map(|path| path.query(credential))
.any(|value| {
if let serde_json::Value::Array(vals) = value {
if let Json::Array(vals) = value {
if vals.iter().any(|val| validator.validate(val).is_ok()) {
return true;
}
Expand All @@ -248,7 +245,7 @@ pub struct SubmissionRequirementObject {
pub name: Option<String>,
pub purpose: Option<String>,
#[serde(flatten)]
pub property_set: Option<Map<String, serde_json::Value>>,
pub property_set: Option<Map<String, Json>>,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
Expand Down

0 comments on commit 7036303

Please sign in to comment.