Skip to content

Commit

Permalink
use flattener for facts, allow arbitrary ucan facts
Browse files Browse the repository at this point in the history
  • Loading branch information
chunningham committed Oct 6, 2023
1 parent 663c66d commit 293792a
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 45 deletions.
16 changes: 11 additions & 5 deletions src/v3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct Cacao<V, S, F, NB = Ipld> {
skip_serializing_if = "Option::is_none",
default = "Option::default"
)]
facts: Option<F>,
facts: Option<Flattener<F>>,
#[serde(rename = "s", bound = "S: VarSigTrait")]
signature: VarSig<S>,
}
Expand Down Expand Up @@ -80,7 +80,7 @@ impl<V, S, F, NB> Cacao<V, S, F, NB> {
}

pub fn facts(&self) -> Option<&F> {
self.facts.as_ref()
self.facts.as_ref().map(|f| &f.f)
}

pub fn signature(&self) -> &VarSig<S> {
Expand All @@ -101,7 +101,7 @@ impl<V, S, F, NB> Cacao<V, S, F, NB> {

pub async fn verify<VE>(&self, verifier: &VE) -> Result<(), VE::Error>
where
VE: CacaoVerifier<V, S, F, NB>,
VE: CacaoVerifier<Self>,
NB: Send + Sync,
{
verifier.verify(self).await
Expand All @@ -110,8 +110,14 @@ impl<V, S, F, NB> Cacao<V, S, F, NB> {

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait CacaoVerifier<V, S, F, NB> {
pub trait CacaoVerifier<C> {
type Error: std::error::Error;

async fn verify(&self, cacao: &Cacao<V, S, F, NB>) -> Result<(), Self::Error>;
async fn verify(&self, cacao: &C) -> Result<(), Self::Error>;
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)]
struct Flattener<T> {
#[serde(flatten)]
pub f: T,
}
20 changes: 10 additions & 10 deletions src/v3/payload.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::Cacao;
use super::{Cacao, Flattener};
use libipld::cid::Cid;
use multidid::MultiDid;
use serde::{Deserialize, Serialize};
Expand All @@ -7,9 +7,9 @@ use ucan_capabilities_object::Capabilities;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)]
#[serde(deny_unknown_fields)]
pub struct Payload<V, F, NB> {
pub struct Payload<V, F, NB, I = MultiDid> {
#[serde(rename = "iss")]
pub issuer: MultiDid,
pub issuer: I,
#[serde(rename = "aud")]
pub audience: MultiDid,
#[serde(rename = "v")]
Expand All @@ -34,8 +34,8 @@ pub struct Payload<V, F, NB> {
pub facts: Option<F>,
}

impl<V, F, NB> Payload<V, F, NB> {
pub(crate) fn new(issuer: MultiDid, audience: MultiDid, version: V) -> Self {
impl<V, F, NB, I> Payload<V, F, NB, I> {
pub(crate) fn new(issuer: I, audience: MultiDid, version: V) -> Self {
Self {
issuer,
audience,
Expand Down Expand Up @@ -86,9 +86,9 @@ impl<V, F, NB> Payload<V, F, NB> {
}

#[derive(Debug, Clone, PartialEq, Serialize, Eq, Hash)]
pub(crate) struct BorrowedPayload<'a, V, F, NB> {
pub(crate) struct BorrowedPayload<'a, V, F, NB, I = MultiDid> {
#[serde(rename = "iss")]
issuer: &'a MultiDid,
issuer: &'a I,
#[serde(rename = "aud")]
audience: &'a MultiDid,
#[serde(rename = "v")]
Expand All @@ -110,7 +110,7 @@ pub(crate) struct BorrowedPayload<'a, V, F, NB> {
skip_serializing_if = "Option::is_none",
default = "Option::default"
)]
facts: &'a Option<F>,
facts: Option<Flattener<&'a F>>,
}

impl<'a, V, S, F, NB> From<&'a Cacao<V, S, F, NB>> for BorrowedPayload<'a, V, F, NB> {
Expand All @@ -125,7 +125,7 @@ impl<'a, V, S, F, NB> From<&'a Cacao<V, S, F, NB>> for BorrowedPayload<'a, V, F,
issued_at: &cacao.issued_at,
not_before: &cacao.not_before,
expiration: &cacao.expiration,
facts: &cacao.facts,
facts: cacao.facts.as_ref().map(|f| Flattener { f: &f.f }),
}
}
}
Expand All @@ -142,7 +142,7 @@ impl<'a, V, F, NB> From<&'a Payload<V, F, NB>> for BorrowedPayload<'a, V, F, NB>
issued_at: &payload.issued_at,
not_before: &payload.not_before,
expiration: &payload.expiration,
facts: &payload.facts,
facts: payload.facts.as_ref().map(|f| Flattener { f }),
}
}
}
26 changes: 14 additions & 12 deletions src/v3/recap_cacao.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{payload::Payload, Cacao, CacaoVerifier};
use super::{payload::Payload, Cacao, CacaoVerifier, Flattener};
use async_trait::async_trait;
use http::uri::Authority;
use iri_string::types::UriString;
Expand Down Expand Up @@ -119,14 +119,16 @@ where
issued_at: Some(issued_at),
not_before,
expiration,
facts: Some(RecapFacts {
iat_info,
nbf_info,
exp_info,
domain: siwe.domain,
request_id: siwe.request_id,
resources,
statement,
facts: Some(Flattener {
f: RecapFacts {
iat_info,
nbf_info,
exp_info,
domain: siwe.domain,
request_id: siwe.request_id,
resources,
statement,
},
}),
signature: VarSig::new(Ethereum::new(sig)),
})
Expand All @@ -146,7 +148,7 @@ where
Method::Pkh(DidPkhTypes::Eip155(eip155)) => eip155.into_inner(),
m => return Err(Error::IncorrectDidType(m)),
};
let facts = cacao.facts.ok_or(Error::MissingFacts)?;
let facts = cacao.facts.ok_or(Error::MissingFacts)?.f;
let mut cap = Capability::new().with_proofs(cacao.proof.unwrap_or_default().iter());
for (resource, actions) in cacao.attenuations.into_inner() {
cap.with_actions(resource, actions);
Expand Down Expand Up @@ -201,7 +203,7 @@ pub struct RecapVerify(());

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<NB> CacaoVerifier<SiweVersion, RecapSignature, RecapFacts, NB> for RecapVerify
impl<NB> CacaoVerifier<RecapCacao<NB>> for RecapVerify
where
NB: Send + Sync + Serialize + Clone,
{
Expand Down Expand Up @@ -232,7 +234,7 @@ impl<NB> Payload<SiweVersion, RecapFacts, NB> {
issued_at: self.issued_at,
not_before: self.not_before,
expiration: self.expiration,
facts: self.facts,
facts: self.facts.map(|f| Flattener { f }),
signature: VarSig::new(sig),
}
}
Expand Down
24 changes: 12 additions & 12 deletions src/v3/ucan_cacao.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{payload::Payload, Cacao, CacaoVerifier};
use super::{payload::Payload, Cacao, CacaoVerifier, Flattener};
use async_trait::async_trait;
use multidid::MultiDid;
use serde::{Deserialize, Serialize};
Expand All @@ -18,8 +18,8 @@ use varsig::{
};

pub type UcanSignature = JoseSig<DAG_JSON_ENCODING>;
pub type UcanFacts<F> = BTreeMap<String, F>;
pub type UcanCacao<F = Value, NB = Value> = Cacao<SemanticVersion, UcanSignature, UcanFacts<F>, NB>;
pub type UcanCacao<F = BTreeMap<String, Value>, NB = Value> =
Cacao<SemanticVersion, UcanSignature, F, NB>;

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand All @@ -37,22 +37,22 @@ impl From<jwt::EncodeError> for Error {

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<NB, R, F> CacaoVerifier<SemanticVersion, UcanSignature, UcanFacts<F>, NB> for &R
impl<NB, R, F> CacaoVerifier<UcanCacao<BTreeMap<String, F>, NB>> for &R
where
R: DIDResolver,
F: Send + Sync + for<'a> Deserialize<'a> + Serialize + Clone,
NB: Send + Sync + for<'a> Deserialize<'a> + Serialize + Clone,
{
type Error = Error;

async fn verify(&self, cacao: &UcanCacao<F, NB>) -> Result<(), Error> {
async fn verify(&self, cacao: &UcanCacao<BTreeMap<String, F>, NB>) -> Result<(), Error> {
let ucan = Ucan::<F, NB, Signature>::from(cacao.clone()).encode()?;
Ucan::<F, NB, Signature>::decode_and_verify_jwt(&ucan, *self, None).await?;
Ok(())
}
}

impl<F, NB> TryFrom<Ucan<F, NB, Signature>> for UcanCacao<F, NB> {
impl<F, NB> TryFrom<Ucan<F, NB, Signature>> for UcanCacao<BTreeMap<String, F>, NB> {
type Error = Error;
fn try_from(ucan: Ucan<F, NB, Signature>) -> Result<Self, Self::Error> {
let (payload, signature) = ucan.into_inner();
Expand All @@ -66,7 +66,7 @@ impl<F, NB> TryFrom<Ucan<F, NB, Signature>> for UcanCacao<F, NB> {
issued_at: payload.issued_at,
not_before: payload.not_before,
expiration: payload.expiration,
facts: payload.facts,
facts: payload.facts.map(|f| Flattener { f }),
signature: VarSig::new(match signature {
Signature::ES256(sig) => JoseSig::Es256(Es256::new(sig)),
Signature::ES512(sig) => JoseSig::Es512(Es512::new(sig)),
Expand All @@ -79,8 +79,8 @@ impl<F, NB> TryFrom<Ucan<F, NB, Signature>> for UcanCacao<F, NB> {
}
}

impl<F, NB> From<UcanCacao<F, NB>> for Ucan<F, NB, Signature> {
fn from(cacao: UcanCacao<F, NB>) -> Self {
impl<F, NB> From<UcanCacao<BTreeMap<String, F>, NB>> for Ucan<F, NB, Signature> {
fn from(cacao: UcanCacao<BTreeMap<String, F>, NB>) -> Self {
let signature = match cacao.signature.into_inner() {
JoseSig::EdDSA(s) => Signature::EdDSA(s.into_inner()),
JoseSig::Es256(s) => Signature::ES256(s.into_inner()),
Expand All @@ -96,7 +96,7 @@ impl<F, NB> From<UcanCacao<F, NB>> for Ucan<F, NB, Signature> {
payload.issued_at = cacao.issued_at;
payload.not_before = cacao.not_before;
payload.expiration = cacao.expiration;
payload.facts = cacao.facts;
payload.facts = cacao.facts.map(|f| f.f);
payload.sign(signature)
}
}
Expand All @@ -107,7 +107,7 @@ impl<F, NB> UcanCacao<F, NB> {
}
}

impl<F, NB> Payload<SemanticVersion, UcanFacts<F>, NB> {
impl<F, NB> Payload<SemanticVersion, F, NB> {
pub fn sign(self, sig: UcanSignature) -> UcanCacao<F, NB> {
Cacao {
issuer: self.issuer,
Expand All @@ -119,7 +119,7 @@ impl<F, NB> Payload<SemanticVersion, UcanFacts<F>, NB> {
issued_at: self.issued_at,
not_before: self.not_before,
expiration: self.expiration,
facts: self.facts,
facts: self.facts.map(|f| Flattener { f }),
signature: VarSig::new(sig),
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/v3/webauthn.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Cacao, CacaoVerifier};
use super::{Cacao, CacaoVerifier, Flattener};
use async_trait::async_trait;
use libipld::cid::{
multihash::{Code, Multihash, MultihashDigest},
Expand Down Expand Up @@ -44,7 +44,7 @@ pub enum Error {

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<NB, R, F> CacaoVerifier<WebauthnVersion, WebauthnSignature, F, NB> for &R
impl<NB, R, F> CacaoVerifier<WebauthnCacao<F, NB>> for &R
where
R: DIDResolver,
F: Send + Sync + for<'a> Deserialize<'a> + Serialize,
Expand Down Expand Up @@ -184,7 +184,7 @@ impl<F, NB> Payload<F, NB> {
issued_at: self.issued_at,
not_before: self.not_before,
expiration: self.expiration,
facts: self.facts,
facts: self.facts.map(|f| Flattener { f }),
signature: VarSig::new(sig),
}
}
Expand Down Expand Up @@ -224,7 +224,7 @@ pub(crate) struct BorrowedPayload<'a, F, NB> {
skip_serializing_if = "Option::is_none",
default = "Option::default"
)]
facts: &'a Option<F>,
facts: Option<&'a F>,
}

impl<'a, F, NB> BorrowedPayload<'a, F, NB> {
Expand Down Expand Up @@ -255,7 +255,7 @@ impl<'a, F, NB> From<&'a WebauthnCacao<F, NB>> for BorrowedPayload<'a, F, NB> {
issued_at: &cacao.issued_at,
not_before: &cacao.not_before,
expiration: &cacao.expiration,
facts: &cacao.facts,
facts: cacao.facts.as_ref().map(|f| &f.f),
}
}
}
Expand All @@ -271,7 +271,7 @@ impl<'a, F, NB> From<&'a Payload<F, NB>> for BorrowedPayload<'a, F, NB> {
issued_at: &payload.issued_at,
not_before: &payload.not_before,
expiration: &payload.expiration,
facts: &payload.facts,
facts: payload.facts.as_ref(),
}
}
}
Expand Down

0 comments on commit 293792a

Please sign in to comment.