You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following are the relevant types for consumers of the library:
VerifiableCredential to represent the data model that's defined in the spec in https://www.w3.org/TR/vc-data-model/). But (and this is important), it is not secured. That is, there is no way for a consumer who has an object of this type to know whether the contents have been integrity checked.
String, which represents a verifiable credential secured as a JWT.
Use Cases
Typical use cases of this API depend on what role the implementer is aiming to fulfill. More details are shown below.
Use case 1: Verifier
Assuming a verifier is being implemented, a consumer of the API will be expected to have something similar to the following snippet of code
val vcJwt ="some VC from the interwebs"try {
VerifiableCredential.verify(vcJwt)
} catch (e:Exception) {
// this credential cannot be trusted!
}
val vc =VerifiableCredential.parseJwt(vcJwt)
myCustomBusinessLogic(vc)
Use Case 2: Issuer
Assuming an issuer is being implemented, a consumer of the API will be expected to have something similar to the following snippet of code
data classDateOfBirth(valdateOfBirth:String)
val vc =VerifiableCredential.create(
type ="DateOfBirth",
issuer = issuerDid.uri,
subject = holderDid.uri,
data =DateOfBirth(dateOfBirth ="01-02-03")
)
val vcJwt = vc.sign(issuerDid)
shipTheVcJwtSomewhere(vcJwt)
Use Case 3: Holder
Holders are a bit of a special case, because they will actually be issuing VCs (e.g. a self-issued credentials), verifying VCs, and displaying the content from a VC to the user, so they can select which VCs to send over. The code for issuing and verifying use cases is similar to the one above. For display purposes, they'll do something similar to the following
// Let `table` be a handle towards a view which will be rendering properties of the credentials. val table:VCTable// Assume that the vcJwt is stored in a credentialStore.val vcs:Iterable<String> = credentialStore.getAllVerifiableCredentials()
vcs.map { VerifiableCredential.parseJwt(it) }.forEach {
it.vcDataModel.credentialSubject.claims.forEach { property, value -> table.addRow(property, value) }
}
Problem
For use case 1 above (the issuer), the current API facilitates doing the following.
val vcJwt ="super bad guy faking bad stuff jwt"val vc =VerifiableCredential.parseJwt(vcJwt)
This can have catastrophic consequences because the content of the VC might have been tampered! Consumers of the API might assume that parseJwt does signature verification and validation of the data within the credential. Can we do better?
Proposed new API
No footguns can be achieved by slightly tweaking the API, and introducing new types. The following API surfaces simplifies and makes it much harde to misuse.
Adding a VerifiableCredentialJWT class with the method verifyAndParse.
Removing the VerifiableCredential.parseJwt method.
Changing the return type of VerifiableCredential.sign so that it's a VerifiableCredentialJWT.
With the API above, the use case 1 then becomes:
val vcJwt =VerifiableCredentialJWT("some VC from the interwebs")
try {
val vc = vcJwt.verify()
} catch (e:Exception) {
// dragons be here
}
myCustomBusinessLogic(vc)
It's hard to misuse, because there is only one mechanism for going from a vcJwt -> VerifiableCredential.
There exists a tradeoff for the holder use case, because verification will be performed every time after retrieving from the credentialStore. I argue that this is ok, and it's really up to the implementer to decide how and what they're going to store. For example, in ssi-service (which acts as a holder) stores a number of things.
Future Work
A whole separate conversation to be had involves removing third party packages from the API. In this case, the type com.danubetech.verifiablecredentials.VerifiableCredential is currently public. We should strive to make it private, but it's out of scope for this issue.
Feedback is welcome!
The text was updated successfully, but these errors were encountered:
Current State
The API for verifiable credential looks as follows:
The following are the relevant types for consumers of the library:
VerifiableCredential
to represent the data model that's defined in the spec in https://www.w3.org/TR/vc-data-model/). But (and this is important), it is not secured. That is, there is no way for a consumer who has an object of this type to know whether the contents have been integrity checked.String
, which represents a verifiable credential secured as a JWT.Use Cases
Typical use cases of this API depend on what role the implementer is aiming to fulfill. More details are shown below.
Use case 1: Verifier
Assuming a verifier is being implemented, a consumer of the API will be expected to have something similar to the following snippet of code
Use Case 2: Issuer
Assuming an issuer is being implemented, a consumer of the API will be expected to have something similar to the following snippet of code
Use Case 3: Holder
Holders are a bit of a special case, because they will actually be issuing VCs (e.g. a self-issued credentials), verifying VCs, and displaying the content from a VC to the user, so they can select which VCs to send over. The code for issuing and verifying use cases is similar to the one above. For display purposes, they'll do something similar to the following
Problem
For use case 1 above (the issuer), the current API facilitates doing the following.
This can have catastrophic consequences because the content of the VC might have been tampered! Consumers of the API might assume that
parseJwt
does signature verification and validation of the data within the credential. Can we do better?Proposed new API
No footguns can be achieved by slightly tweaking the API, and introducing new types. The following API surfaces simplifies and makes it much harde to misuse.
The changes include:
VerifiableCredentialJWT
class with the methodverifyAndParse
.VerifiableCredential.parseJwt
method.VerifiableCredential.sign
so that it's aVerifiableCredentialJWT
.With the API above, the use case 1 then becomes:
It's hard to misuse, because there is only one mechanism for going from a
vcJwt
->VerifiableCredential
.There exists a tradeoff for the holder use case, because verification will be performed every time after retrieving from the
credentialStore
. I argue that this is ok, and it's really up to the implementer to decide how and what they're going to store. For example, inssi-service
(which acts as a holder) stores a number of things.Future Work
A whole separate conversation to be had involves removing third party packages from the API. In this case, the type
com.danubetech.verifiablecredentials.VerifiableCredential
is currently public. We should strive to make it private, but it's out of scope for this issue.Feedback is welcome!
The text was updated successfully, but these errors were encountered: