spruceid / ssi

Core library for decentralized identity.
https://spruceid.dev
Apache License 2.0
192 stars 61 forks source link

Feature request: Add ability to set "exp" and "nbf" for JWT formatted verifiable presentations #387

Open vdods opened 2 years ago

vdods commented 2 years ago

Verifiable Credential (ssi::vc::Credential) has expiration_date and not_before fields which map onto the exp and nbf claims of a JWT, but Verifiable Presentation (ssi::vc::Presentation) is missing those, so it's not possible to properly time-limit a VP.

Would adding this capability be as simple as copying those fields from ssi::vc::Credential into ssi::vc::Presentation and hooking up appropriate plumbing? Or is there an active reason it's missing? If it's the former, I'd be happy to take a crack at it.

vdods commented 2 years ago

Somewhat related: The default for LinkedDataProofOptions includes setting the created timestamp to "now", but then presentation.generate_jwt fails with Linked data proof option unencodable as JWT claim: created.

clehner commented 2 years ago

Would adding this capability be as simple as copying those fields from ssi::vc::Credential into ssi::vc::Presentation and hooking up appropriate plumbing? Or is there an active reason it's missing?

Some additional changes may be needed for JSON-LD Verifiable Presentations. The Credentials base JSON-LD context defines the relevant terms only in the scope of the VerifiableCredential type, not in VerifiablePresentation. So for the properties to be used in a Verifiable Presentation that uses JSON-LD/RDF signatures/proofs or otherwise must be valid JSON-LD, those terms will needed to be defined in inline context, or in a new context file, or used as URIs/IRIs instead of short property names.

I don't see the VC Data Model saying a lot about the mapping of date properties to/from JWT. There is a (non-normative) example of a VP-JWT using exp, iat, and nbf: https://www.w3.org/TR/vc-data-model/#example-jwt-payload-of-a-jwt-based-verifiable-credential-using-jws-as-a-proof-non-normative - although use of the "iat" claim is not mentioned in VC Data Model. The mapping of "exp" and "nbf" is defined for verifiable credential JWTs, but for verifiable presentation JWTs I think it can only be inferred in VC Data Model 1.0

There are changes going into VC Data Model 1.1 that seem to broaden or generalize the VC JWT parameters for use with VPs: https://github.com/w3c/vc-data-model/pull/828/files#diff-0eb547304658805aad788d320f10bf1f292797b5e6d745a3bf617584da017051L3603-R3667. I think those changes imply that the mapping for exp and nbf can be done with a (verifiable) presentation as well as with a (verifiable) credential. However the JSON-LD term definition is still needed. Maybe a future Credentials context will define it.

There's also discussion about the meaning and mapping of the date claims/parameters, e.g. here: https://github.com/w3c/vc-data-model/issues/844 It looks reasonable to me at this point to continue using the terms as they are specified in VC Data Model. In the future it might need to be switched if things change (e.g. to use validFrom and validUntil instead of issuanceDate and expirationDate, as mentioned in https://github.com/w3c/vc-data-model/issues/844#issuecomment-982084036).

Even though VC Data Model discusses issuanceDate and expirationDate as properties of a credential, I think the open-world idea means that as a term it can be used in other places as well.

According to this vocabulary document, however, the domain of the issuanceDate and expirationDate terms is defined to be cred:VerifiableCredential: https://w3c.github.io/vc-data-model/vocab/credentials/credentials.html - which I think would suggest it's not correct to use these properties as predicates where the subject is something that is not a credential. Maybe this could be a proposed change (like https://github.com/w3c/vc-data-model/pull/771). ssi isn't doing RDF Schema processing, so it doesn't cause an implementation problem here. Also, the termsOfUse property has the same domain but is shown as being usable in a verifiable presentation, in this example using inline context: https://www.w3.org/TR/vc-data-model/#example-usage-of-the-termsofuse-property-by-a-holder (https://github.com/w3c/vc-data-model/pull/787).

Somewhat related: The default for LinkedDataProofOptions includes setting the created timestamp to "now", but then presentation.generate_jwt fails with Linked data proof option unencodable as JWT claim: created.

Yes, created has to be overwritten to None. It's not ideal; basically LinkedDataProofOptions needs two defaults, one for VPs and one for VCs (or more, if considering ZCaps and generalized linked data signatures). The LinkedDataProofOptions type should probably be replaced with multiple different types, as was done in VC (HTTP) API where it was originally defined. VC API replaced it with three types: IssueCredentialOptions, PresentCredentialOptions, and VerifyOptions: https://github.com/w3c-ccg/vc-api/pull/92 (https://github.com/w3c-ccg/vc-api/tree/9153982/components).

vdods commented 2 years ago

Thanks for the detailed answer. I had no idea how involved the issue was ;)

For now, I'm just doing basic DIDAuth, and ideally the VP would have a short validity duration. Would it be appropriate to use a VC for DIDAuth? I'm having trouble finding any definitive documentation from W3C (or anyone) detailing DIDAuth.

clehner commented 2 years ago

VC for DIDAuth could probably work, i.e. self-issue a VC and present that, or pass the VC directly. But I think VPs are more expected to be used for authentication rather than VCs. And VCs are supposed to be exchanged wrapped in a (verifiable) presentation. Although a VP with embedded VC could accomplish the same authentication as a VP without embedded VC, if you don't actually need to present a verifiable credential then the VC can be omitted and you don't have to generate a "dummy" VC.

DIF's implementation https://github.com/decentralized-identity/did-jwt-vc/ supports VP issuance/expiration dates, i.e. the following:

Besides iat (which ssi has not yet needed to support), the rest of the above mappings appear consistent with what ssi does for VCs. In the absence of more documentation, other examples, etc., I think it would make sense to align with the did-jwt-vc implementation. It also appears to support VP without VC: https://github.com/decentralized-identity/did-jwt-vc/pull/83. It's also not doing anything special with JSON-LD when adding issuanceDate/expirationDate to a VP; I think that means it leaves it up to the caller/client to make sure that the @context is correct on the JSON-LD side.