Skip to content

Commit

Permalink
add data integrity conversion for vp token (#42)
Browse files Browse the repository at this point in the history
* add request object signing algorithm setter method

Signed-off-by: Ryan Tate <[email protected]>

* return application json encoded authorization response (#39)

* use serde deserialize serialize derive for authorization response

Signed-off-by: Ryan Tate <[email protected]>

* update url encoding for auth response

Signed-off-by: Ryan Tate <[email protected]>

* fix unit tests

Signed-off-by: Ryan Tate <[email protected]>

* use custom struct for json string encoded authorization response inner values

Signed-off-by: Ryan Tate <[email protected]>

---------

Signed-off-by: Ryan Tate <[email protected]>

* bump serde_json_path version

Signed-off-by: Ryan Tate <[email protected]>

* Add temporary support for unencoded JWT authorization requests

* Remove unnecessary comment

* Start implementation for VpTokenItem From method for specific JsonPresentation

Signed-off-by: Ryan Tate <[email protected]>
Co-Authored-By: Joey Silberman <[email protected]>

* use ssi 0.10.1 release

Signed-off-by: Ryan Tate <[email protected]>

* add data integrity conversion for vp token

Additionally adds a check for authorization request
vp formats supported to check cryptosuite against
expected response formats.

Signed-off-by: Ryan Tate <[email protected]>

* update data integrity vp token from conversion

Signed-off-by: Ryan Tate <[email protected]>

* Feat/support unencoded jwt authorization requests (#40)

* Add temporary support for unencoded JWT authorization requests

* Remove unnecessary comment

* use serde deserialize serialize derive for authorization response

Signed-off-by: Ryan Tate <[email protected]>

* update url encoding for auth response

Signed-off-by: Ryan Tate <[email protected]>

* fix unit tests

Signed-off-by: Ryan Tate <[email protected]>

* use custom struct for json string encoded authorization response inner values

Signed-off-by: Ryan Tate <[email protected]>

* allow unencoded authorization request

Signed-off-by: Ryan Tate <[email protected]>

---------

Signed-off-by: Ryan Tate <[email protected]>
Co-authored-by: Joey Silberman <[email protected]>
Co-authored-by: Ryan Tate <[email protected]>

* Update src/core/metadata/parameters/verifier.rs

Co-authored-by: Jacob <[email protected]>
Signed-off-by: Ryan Tate <[email protected]>

---------

Signed-off-by: Ryan Tate <[email protected]>
Co-authored-by: Joey Silberman <[email protected]>
Co-authored-by: Joey Silberman <[email protected]>
Co-authored-by: Jacob <[email protected]>
  • Loading branch information
4 people authored Dec 1, 2024
1 parent 427c766 commit 592f3b9
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ reqwest = { version = "0.12.5", features = ["rustls-tls"] }
serde = "1.0.188"
serde_json = "1.0.107"
serde_urlencoded = "0.7.1"
ssi = { version = "0.10", features = ["secp256r1"] }
ssi = { version = "0.10.1", features = ["secp256r1"] }
tokio = "1.32.0"
tracing = "0.1.37"
url = { version = "2.4.1", features = ["serde"] }
Expand Down
17 changes: 17 additions & 0 deletions src/core/authorization_request/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::ops::{Deref, DerefMut};

use anyhow::{anyhow, bail, Context, Error, Result};
use parameters::ClientMetadata;
use serde::{Deserialize, Serialize};
use serde_json::Value as Json;
use url::Url;
Expand All @@ -16,6 +17,7 @@ use self::{
};

use super::{
metadata::parameters::verifier::VpFormats,
object::{ParsingErrorContext, UntypedObject},
util::{base_request, AsyncHttpClient},
};
Expand Down Expand Up @@ -263,6 +265,21 @@ impl AuthorizationRequestObject {
pub fn nonce(&self) -> &Nonce {
&self.7
}

/// Return the `client_metadata` field from the authorization request.
pub fn client_metadata(&self) -> Result<ClientMetadata> {
self.0
.get()
.ok_or(anyhow!("missing `client_metadata` object"))?
}

/// Return the `VpFormats` from the `client_metadata` field.
pub fn vp_formats(&self) -> Result<VpFormats> {
self.client_metadata()?
.0
.get()
.ok_or(anyhow!("missing vp_formats"))?
}
}

impl From<AuthorizationRequestObject> for UntypedObject {
Expand Down
8 changes: 8 additions & 0 deletions src/core/authorization_request/verification/did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ pub async fn verify_with_resolver(
bail!("request was signed with unsupported algorithm: {alg}")
}

// This bypass is for unencoded JWT requests, but we will need to change this later
// so that trust is preserved when receiving unencoded requests
// NOTE: This requires that `Algorithm::None` is permitted in the wallet metadata
// Otherwise, this function will error in the previous assertion.
if alg.contains("none") {
return Ok(());
}

let Json::String(kid) = headers
.remove("kid")
.context("'kid' was missing from jwt headers")?
Expand Down
1 change: 1 addition & 0 deletions src/core/credential_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ pub enum ClaimFormatPayload {
/// claim presentation algorithm types supported by a wallet.
#[serde(rename = "alg_values_supported")]
AlgValuesSupported(Vec<String>),
/// This variant is primarily used for `ldp`, `ldp_vc`, `ldp_vp`, `ac_vc`, and `ac_vp`
#[serde(rename = "proof_type")]
ProofType(Vec<String>),
#[serde(untagged)]
Expand Down
5 changes: 5 additions & 0 deletions src/core/input_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ impl Constraints {
self.fields.as_ref()
}

/// Returns the fields of the constraints object as a mutable reference.
pub fn fields_mut(&mut self) -> &mut Vec<ConstraintsField> {
self.fields.as_mut()
}

/// Set the limit disclosure value.
///
/// For all [Claims](https://identity.foundation/presentation-exchange/spec/v2.0.0/#term:claims) submitted in relation to [InputDescriptor] Objects that include a `constraints`
Expand Down
31 changes: 30 additions & 1 deletion src/core/metadata/parameters/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::core::credential_format::ClaimFormatMap;
use crate::core::metadata::ClaimFormatPayload;
use crate::core::object::TypedParameter;
use crate::core::{credential_format::ClaimFormatMap, metadata::ClaimFormatDesignation};

use anyhow::{Context, Error};
use serde::{Deserialize, Serialize};
Expand All @@ -8,6 +9,34 @@ use serde_json::{Map, Value as Json};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VpFormats(pub ClaimFormatMap);

impl VpFormats {
/// Returns a boolean to denote whether a particular pair of format and security method
/// are supported in the VP formats. A security method could be a JOSE algorithm, a COSE
/// algorithm, a Cryptosuite, etc.
///
/// NOTE: This method is interested in the security method of the claim format
/// payload and not the claim format designation.
///
/// For example, the security method would need to match one of the `alg`
/// values in the claim format payload.
pub fn supports_security_method(
&self,
format: &ClaimFormatDesignation,
security_method: &String,
) -> bool {
match self.0.get(format) {
Some(ClaimFormatPayload::Alg(alg_values))
| Some(ClaimFormatPayload::AlgValuesSupported(alg_values)) => {
alg_values.contains(security_method)
}
Some(ClaimFormatPayload::ProofType(proof_types)) => {
proof_types.contains(security_method)
}
_ => false,
}
}
}

impl TypedParameter for VpFormats {
const KEY: &'static str = "vp_formats";
}
Expand Down
56 changes: 55 additions & 1 deletion src/core/response/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ use crate::core::object::TypedParameter;
use anyhow::Error;
use serde::{Deserialize, Serialize};
use serde_json::Value as Json;
use ssi::{claims::vc, one_or_many::OneOrManyRef, prelude::AnyJsonPresentation, OneOrMany};
use ssi::{
claims::vc::{self, v2::SpecializedJsonCredential},
json_ld::syntax::Object,
one_or_many::OneOrManyRef,
prelude::{AnyDataIntegrity, AnyJsonPresentation, AnySuite, DataIntegrity},
OneOrMany,
};

#[derive(Debug, Clone)]
pub struct IdToken(pub String);
Expand Down Expand Up @@ -106,6 +112,12 @@ impl From<vc::v2::syntax::JsonPresentation> for VpToken {
}
}

impl From<vc::v2::syntax::JsonPresentation<SpecializedJsonCredential<Object>>> for VpToken {
fn from(value: vc::v2::syntax::JsonPresentation<SpecializedJsonCredential<Object>>) -> Self {
Self(vec![value.into()])
}
}

impl From<AnyJsonPresentation> for VpToken {
fn from(value: AnyJsonPresentation) -> Self {
Self(vec![value.into()])
Expand Down Expand Up @@ -159,6 +171,20 @@ impl From<String> for VpTokenItem {
}
}

impl From<AnyDataIntegrity> for VpTokenItem {
fn from(value: AnyDataIntegrity) -> Self {
let serde_json::Value::Object(obj) = serde_json::to_value(&value)
// SAFETY: by definition a Data Integrity Object is a Json LD Node and is a JSON object.
.unwrap()
else {
// SAFETY: by definition a Data Integrity Object is a Json LD Node and is a JSON object.
unreachable!()
};

Self::JsonObject(obj)
}
}

impl From<vc::v1::syntax::JsonPresentation> for VpTokenItem {
fn from(value: vc::v1::syntax::JsonPresentation) -> Self {
let serde_json::Value::Object(obj) = serde_json::to_value(value)
Expand Down Expand Up @@ -187,6 +213,20 @@ impl From<vc::v2::syntax::JsonPresentation> for VpTokenItem {
}
}

impl From<vc::v2::syntax::JsonPresentation<SpecializedJsonCredential<Object>>> for VpTokenItem {
fn from(value: vc::v2::syntax::JsonPresentation<SpecializedJsonCredential<Object>>) -> Self {
let serde_json::Value::Object(obj) = serde_json::to_value(value)
// SAFETY: by definition a VCDM2.0 presentation is a JSON object.
.unwrap()
else {
// SAFETY: by definition a VCDM2.0 presentation is a JSON object.
unreachable!()
};

Self::JsonObject(obj)
}
}

impl From<AnyJsonPresentation> for VpTokenItem {
fn from(value: AnyJsonPresentation) -> Self {
let serde_json::Value::Object(obj) = serde_json::to_value(value)
Expand All @@ -200,3 +240,17 @@ impl From<AnyJsonPresentation> for VpTokenItem {
Self::JsonObject(obj)
}
}

impl From<DataIntegrity<AnyJsonPresentation, AnySuite>> for VpTokenItem {
fn from(value: DataIntegrity<AnyJsonPresentation, AnySuite>) -> Self {
let serde_json::Value::Object(obj) = serde_json::to_value(value)
// SAFETY: by definition a VCDM2.0 presentation is a JSON object.
.unwrap()
else {
// SAFETY: by definition a VCDM2.0 presentation is a JSON object.
unreachable!()
};

Self::JsonObject(obj)
}
}

0 comments on commit 592f3b9

Please sign in to comment.