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

Multi-credential Model #1313

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft

Multi-credential Model #1313

wants to merge 10 commits into from

Conversation

UMR1352
Copy link
Contributor

@UMR1352 UMR1352 commented Feb 27, 2024

Very clanky but it lets us discuss the design with some code at hand

@UMR1352
Copy link
Contributor Author

UMR1352 commented Feb 28, 2024

Credentials' traits summed up

First and foremost we have CredentialT which abstracts out the minimal behavior of any credential: having an id, an issuer, an issuance time, an optional expiration time and some claims.
Then we have VerifiableCredentialT which can only be implemented over CredentialT. Here it is:

pub trait VerifiableCredentialT<'c>: CredentialT {
  type Proof;

  fn proof(&'c self) -> Self::Proof;
}

Discussion: the 'c lifetime allows implementers to either return an owned or borrowed (with the lifetime of the underlying credential) proof. If we remove the 'c we'll have to only return a &Proof which will require implementers to have the proof actually stored in the struct losing the ability to construct it on the fly (which may not be needed??). Moreover having Proof as an associated type rather than a generic type parameter forces credentials to only have exactly 1 proof rather than many. This can be overcome through appropriate conversions (through TryFrom<T>) and is actually rather nice type constraints-wise later on, but might be undesirable???

Finally we have StatusCredentialT, which enables the get/set operations for the status of a credential.

Discussion: same thing here: the traits imposes that a credential can only have one status and that status has to be embedded into the credential itself. Is this undesirable?
StatusCredentialT comes with another trait: StatusT

pub trait StatusT {
  type State;
  fn type_(&self) -> &str;
}

The associated type State represents the different states a credential with that status can be in (e.g. Valid | Revoked).
It could also be extended with more interesting stuff like a fn is_valid(&self) -> bool.

Jws, Jwt, and JwtCredential

I got JwtCredential all wrong (my fault for misunderstanding JWS). The idea for v2 is to change our current Jwt and Jws to actually represent respectively JWT and JWS encoded data (RN they just wrap any string). Jws should be constructed from a string and actively parsed into header, payload, and signature. Jwt should be parsed out from Jws (not sure what we are supposed to parse here other than certain mandatory headers (typ: jwt) and the claims (e.g. iat, exp, iss..)). Jwt should also be parsed out directly from a string (leveraging Jws behind the scenes). Finally with Jwt done right we can have a JwtCredential<C> which should be constructed like this (mind the type constraints):

impl<C: TryFrom<JwtClaims> + CredentialT> JwtCredential<C> {
  pub fn new(jwt: Jwt) -> Result<Self, JwtCredentialError> {
    todo!()
  }
}

Then JwtCredential should implement CredentialT through its inner C (transparently) but implement VerifiableCredentialT to use Jws as proof.
StatusCredentialT can only be implemented if we have the C type parameter on JwtCredential and the credential parsed out, otherwise it could be basically impossible to implement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant