Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make proof_types_supported requirement optional #84

Merged
merged 3 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions oid4vci/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ serde_with.workspace = true
tokio.workspace = true

[dev-dependencies]
oid4vc-core = { path = "../oid4vc-core", features = ["test-utils"] }
wiremock = "0.5"
138 changes: 132 additions & 6 deletions oid4vci/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,25 +158,43 @@ impl<CFC: CredentialFormatCollection + DeserializeOwned> Wallet<CFC> {
.map_err(|e| e.into())
}

// Select supported signing algorithm that matches the Credential Issuer's supported Proof Types.
// Supplying the `proof` parameter to the Credential Request is only required when the `proof_types_supported`
// parameter is present in the Credential Configuration in the Credential Issuer's metadata. However, if the
// `proof_types_supported` is not present, the Wallet will still provide the `proof` signed with its own preferred
// signing algorithm. For more information see: https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-13.html#section-7.2-2.2.1
fn select_signing_algorithm(
&self,
credential_configuration: &CredentialConfigurationsSupportedObject,
) -> Result<Algorithm> {
let credential_issuer_proof_signing_alg_values_supported = &credential_configuration
.proof_types_supported
let proof_types_supported = &credential_configuration.proof_types_supported;

// If the Credential Issuer does not define any supported Proof Types, then the Wallet wil uses its own default signing algorithm.
if proof_types_supported.is_empty() {
return self
.proof_signing_alg_values_supported
.first()
.ok_or(anyhow::anyhow!("Wallet does not support any signing algorithms"))
.cloned();
}

// Extract the actual signing algorithms if the Credential Issuer supports JWT proof types.
// TODO: support Proof types other than Jwt.
let credential_issuer_proof_signing_alg_values_supported = proof_types_supported
.get(&ProofType::Jwt)
.map(|proof_type| proof_type.proof_signing_alg_values_supported.clone())
.ok_or(anyhow::anyhow!(
"`jwt` proof type is missing from the `proof_types_supported` parameter"
))?
.proof_signing_alg_values_supported;
"The Credential Issuer does not support JWT proof types"
))?;

// Return the first signin algorithm that matches any of the Credential Issuer's supported signing algorithms.
nanderstabel marked this conversation as resolved.
Show resolved Hide resolved
self.proof_signing_alg_values_supported
.iter()
.find(|supported_algorithm| {
credential_issuer_proof_signing_alg_values_supported.contains(supported_algorithm)
})
.cloned()
.ok_or(anyhow::anyhow!("No supported signing algorithm found."))
.ok_or(anyhow::anyhow!("No matching supported signing algorithms found."))
}

fn select_subject_syntax_type(
Expand Down Expand Up @@ -311,3 +329,111 @@ impl<CFC: CredentialFormatCollection + DeserializeOwned> Wallet<CFC> {
.map_err(|e| e.into())
}
}

#[cfg(test)]
pub mod tests {
use super::*;
use crate::proof::KeyProofMetadata;
use oid4vc_core::test_utils::TestSubject;
use std::{collections::HashMap, sync::Arc};

#[test]
fn select_signing_algorithm_returns_first_supported_signing_algorithm_when_no_proof_types_supported() {
// Create a new Wallet.
let wallet: Wallet = Wallet::new(
Arc::new(TestSubject::default()),
vec!["did:test"],
vec![Algorithm::EdDSA],
)
.unwrap();

let signing_algorithm = wallet
// The Credential Issuer does not supply the `proof_types_supported` parameter, so the Wallet will use its own
// preferred signing algorithm
.select_signing_algorithm(&CredentialConfigurationsSupportedObject::default())
.unwrap();

assert_eq!(signing_algorithm, Algorithm::EdDSA);
}

#[test]
fn select_signing_algorithm_returns_error_when_issuers_supported_proof_type_is_not_supported() {
// Create a new Wallet.
let wallet: Wallet = Wallet::new(
Arc::new(TestSubject::default()),
vec!["did:test"],
vec![Algorithm::EdDSA],
)
.unwrap();

let error = wallet
.select_signing_algorithm(&CredentialConfigurationsSupportedObject {
proof_types_supported: HashMap::from_iter(vec![(
// This Proof Type is not supported in the Wallet (as of now) so the Wallet will return an error.
ProofType::Cwt,
KeyProofMetadata {
proof_signing_alg_values_supported: vec![Algorithm::EdDSA],
},
)]),
..Default::default()
})
.unwrap_err()
.to_string();

assert_eq!(error, "The Credential Issuer does not support JWT proof types");
}

#[test]
fn select_signing_algorithm_returns_error_when_it_cannot_find_matching_signing_algorithm() {
// Create a new Wallet.
let wallet: Wallet = Wallet::new(
Arc::new(TestSubject::default()),
vec!["did:test"],
vec![Algorithm::EdDSA],
)
.unwrap();

let error = wallet
.select_signing_algorithm(&CredentialConfigurationsSupportedObject {
proof_types_supported: HashMap::from_iter(vec![(
ProofType::Jwt,
KeyProofMetadata {
// This proof signing algorithm will not match any of the Wallet's supported signing algorithms.
proof_signing_alg_values_supported: vec![Algorithm::RS256],
},
)]),
..Default::default()
})
.unwrap_err()
.to_string();

assert_eq!(error, "No matching supported signing algorithms found.");
}

#[test]
fn select_signing_algorithm_returns_matching_signing_algorithm() {
// Create a new Wallet.
let wallet: Wallet = Wallet::new(
Arc::new(TestSubject::default()),
vec!["did:test"],
vec![Algorithm::EdDSA],
)
.unwrap();

let signing_algorithm = wallet
.select_signing_algorithm(&CredentialConfigurationsSupportedObject {
proof_types_supported: HashMap::from_iter(vec![(
// This Proof Type is supported by the Wallet
ProofType::Jwt,
KeyProofMetadata {
// This proof signing algorithm will match the Wallet's supported signing algorithms.
proof_signing_alg_values_supported: vec![Algorithm::EdDSA],
},
)]),
..Default::default()
})
.unwrap();

assert_eq!(signing_algorithm, Algorithm::EdDSA);
}
}
Loading