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

add vp token encoded to vp builder #15

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions src/core/authorization_request/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::core::{
util::{base_request, AsyncHttpClient},
};
use anyhow::{bail, Context, Error, Ok};
use json_syntax::Value;
use serde::{Deserialize, Serialize};
use serde_json::Value as Json;
use url::Url;
Expand Down Expand Up @@ -208,6 +209,12 @@ impl From<&str> for Nonce {
}
}

impl From<Nonce> for Value {
fn from(value: Nonce) -> Self {
value.0.into()
}
}

impl Deref for Nonce {
type Target = String;

Expand Down
2 changes: 1 addition & 1 deletion src/core/credential_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,6 @@ impl From<&CredentialType> for String {

impl std::fmt::Display for &CredentialType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
write!(f, "{}", String::from(*self))
}
}
41 changes: 27 additions & 14 deletions src/holder/verifiable_presentation_builder.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
use std::time::{SystemTime, UNIX_EPOCH};

use anyhow::{Context, Result};
use base64::prelude::*;
use serde::{Deserialize, Serialize};
use ssi_claims::jwt::{VerifiableCredential, VerifiablePresentation};
use ssi_claims::jwt::VerifiablePresentation;
use ssi_claims::vc::v2::syntax::VERIFIABLE_PRESENTATION_TYPE;
use ssi_dids::ssi_json_ld::CREDENTIALS_V1_CONTEXT;
use ssi_dids::{
ssi_json_ld::syntax::{Object, Value},
DIDURLBuf,
};

use crate::core::authorization_request::parameters::Nonce;
use crate::core::response::parameters::VpToken;

#[derive(Debug, Clone)]
pub struct VerifiablePresentationBuilderOptions {
pub issuer: DIDURLBuf,
pub subject: DIDURLBuf,
pub audience: DIDURLBuf,
pub nonce: String,
pub nonce: Nonce,
// TODO: we may wish to support an explicit
// issuance and expiration date rather than seconds from now.
/// Expiration is in seconds from `now`.
/// e.g. 3600 for 1 hour.
pub expiration_secs: u64,
pub credentials: Vec<VerifiableCredential>,
pub credentials: Value,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -48,7 +53,7 @@ impl VerifiablePresentationBuilder {
///
/// This will set the issuance date to the current time and the expiration
/// date to the expiration secs from the issuance date.
pub fn from_options(options: VerifiablePresentationBuilderOptions) -> VerifiablePresentation {
pub fn from_options(options: VerifiablePresentationBuilderOptions) -> Self {
let mut verifiable_presentation = VerifiablePresentation(Value::Object(Object::new()));

if let Some(obj) = verifiable_presentation.0.as_object_mut() {
Expand All @@ -72,7 +77,7 @@ impl VerifiablePresentationBuilder {
);
}

obj.insert("nonce".into(), Value::String(options.nonce.into()));
obj.insert("nonce".into(), options.nonce.into());

let mut verifiable_credential_field = Value::Object(Object::new());

Expand All @@ -87,16 +92,28 @@ impl VerifiablePresentationBuilder {
Value::String(VERIFIABLE_PRESENTATION_TYPE.to_string().into()),
);

cred.insert(
"verifiableCredential".into(),
Value::Array(options.credentials.into_iter().map(|vc| vc.0).collect()),
);
cred.insert("verifiableCredential".into(), options.credentials);
}

obj.insert("vp".into(), verifiable_credential_field);
}

verifiable_presentation
Self(verifiable_presentation)
}

/// Build the verifiable presentation.
pub fn build(self) -> VerifiablePresentation {
self.0
}

/// Return the verifiable presentation as a base64 encoded verifiable
/// presentation token.
pub fn as_base64_encoded_vp_token(self) -> Result<VpToken> {
let json_string = serde_json::to_string(&self.0).context("Failed to encode JSON string")?;

let token = BASE64_STANDARD.encode(json_string);

Ok(VpToken(token))
}

/// Add an issuer to the verifiable presentation.
Expand Down Expand Up @@ -157,8 +174,4 @@ impl VerifiablePresentationBuilder {
}
self
}

pub fn build(self) -> VerifiablePresentation {
self.0
}
}
15 changes: 7 additions & 8 deletions tests/e2e.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use jwt_vp::create_test_verifiable_presentation;
use jwt_vp::create_test_verifiable_presentation_token;
use oid4vp::{
core::{
authorization_request::parameters::{ClientMetadata, Nonce, ResponseMode, ResponseType},
Expand All @@ -7,7 +7,7 @@ use oid4vp::{
object::UntypedObject,
presentation_definition::*,
presentation_submission::*,
response::{parameters::VpToken, AuthorizationResponse, UnencodedAuthorizationResponse},
response::{AuthorizationResponse, UnencodedAuthorizationResponse},
},
verifier::session::{Outcome, Status},
wallet::Wallet,
Expand Down Expand Up @@ -129,14 +129,13 @@ async fn w3c_vc_did_client_direct_post() {
descriptor_map,
);

let token = create_test_verifiable_presentation_token()
.await
.expect("Failed to create token");

let response = AuthorizationResponse::Unencoded(UnencodedAuthorizationResponse(
Default::default(),
VpToken(
create_test_verifiable_presentation()
.await
.expect("failed to create verifiable presentation")
.to_string(),
),
token,
presentation_submission.try_into().unwrap(),
));

Expand Down
14 changes: 5 additions & 9 deletions tests/jwt_vp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::str::FromStr;

use anyhow::Result;
use base64::prelude::*;
use oid4vp::core::response::parameters::VpToken;
use oid4vp::holder::verifiable_presentation_builder::{
VerifiablePresentationBuilder, VerifiablePresentationBuilderOptions,
};
Expand All @@ -10,7 +10,7 @@ use ssi_claims::jwt;
use ssi_dids::DIDKey;
use ssi_jwk::JWK;

pub async fn create_test_verifiable_presentation() -> Result<String> {
pub async fn create_test_verifiable_presentation_token() -> Result<VpToken> {
let verifier = JWK::from_str(include_str!("examples/verifier.jwk"))?;

let signer = P256Signer::new(
Expand All @@ -34,15 +34,11 @@ pub async fn create_test_verifiable_presentation() -> Result<String> {
subject: holder_did.clone(),
audience: verifier_did.clone(),
expiration_secs: 3600,
credentials: vec![verifiable_credential],
credentials: vec![verifiable_credential.0].into(),
nonce: "random_nonce".into(),
});

// Encode the verifiable presentation as base64 encoded payload.
let vp_token = verifiable_presentation.0.to_string();
let token = verifiable_presentation.as_base64_encoded_vp_token()?;

// encode as base64.
let base64_encoded_vp = BASE64_STANDARD.encode(vp_token);

Ok(base64_encoded_vp)
Ok(token)
}
Loading