We refreshed our doc site!
Bookmarked links may have changed
Read release notesAs users collect more credentials, having to manually manage them (figuring out which are current, and which are appropriate for a given relying party) becomes infeasible. Unlike unstructured credentials (e.g., many .pdf files), which would require a user to manually select which data to share, verifiable credentials lend themselves to credential exchange protocols that are easier for end-users. These protocols are typically implemented for the user through the user's wallet (or other software agents) interacting with the requesting party.
Verite uses the concepts and data models from DIF's Presentation Exchange for this purpose. This document describes how a consumer of Verifiable Credentials, referred to as a verifier or relying party, informs users what types/formats of credentials they accept, and how the user's wallet/agent uses this information to select the appropriate credentials and respond. Note that what follows assumes a wallet that controls a fully-featured DID like did:ion
rather than a crypto-wallet; the latter has a slightly different trust model and identity-binding model, which leads to different requirements for Verifiable Presentation (i.e. proving liveness and consent at time of credential exchange).
A presentation definition is the way a relying party describes the inputs it requires, proof formats, etc. A presentation request is a generic term for a transport conveying this. It's meant to be flexibly embedded in a variety of transports, such as OIDC or WACI. Verite uses a JSON object that somewhat resembles the schema defined by WACI, but with additional fields including a challenge and reply URL.
Assuming a mobile wallet stores the credentials, for the convenience of the user a verifier may initiate the process of sending the presentation request either by scanning a QR code (desktop) or a deep-link (mobile). Due to size limitations of a QR code, wallet and credential interactions often do not include the full presentation request in the QR code; instead the QR code encodes an endpoint with a unique URL. The wallet decodes the QR code, subsequently retrieving the presentation request from that endpoint.
See example Verite Presentation Request
The wallet parses the Presentation Definition object to determine what types of inputs, proofs, and formats the verifier requires. The wallet displays a summary of the information requested to the wallet holder, asking for approval and/or asking the user to select the desired credential(s) from the set of matches. On confirmation, the wallet gathers the credentials and creates a verifiable presentation containing the credential and signs the presentation with the credential subject’s private key. It embeds the VP in a presentation submission, and signs it along with the challenge
to provide proof of identifier control.
Finally, the wallet sends the packaged credential to the reply_url
contained in the presentation request.
See example Verite presentation submission.
The verifier receives the presentation submission, unwraps it, and maps the presentation to the original presentation request. Mapping the submission to the original request can be done in many ways. The Verite demos use a JWT in the reply_url
to store the mapping. Next, the verifier verifies the submitted contents against the required inputs, ensures its signed by the subject's keys, and checking the credential's status to determine if it is revoked out not.
Verification cannot always occur immediately. In these cases, the presentation request has an optional status_url
that can be used to check its status.
There is no required output or side-effect of verification. However, we have a pattern for integrating with Ethereum that models how an on-chain Verification Registry can capture verification events in a way that's easy to consume on-chain. A web app that is not constrained by on-chain data availability, however, might simply update its state and allow the user to continue some action.
At a high level, the verification flow for an identity wallet looks like this:
However, when this maps to an on-chain use-case, where Dapps are requiring off-chain documentation to trust a crypto address, this flow can get a lot more complicated depending on the types of credentials and the identity-proofing they require.
In what follows, we will zoom in one two very different applications of this high-level flow that come from two different architectures: first, we will break down the flow for credentials issued to a user-controlled "identity wallet", then, we will break down the flow for address-specific credentials (signed over by only a crypto-currency wallet), showing the differences in both procedure and trust model.
In this example, a user wants to verify credentials issued to, and stored in a mobile app that function as an "identity wallet," i.e., a wallet controlling a DID for identity applications rather than a "cryptocurrency wallet" controlling a keypair for onchain/payment purposes. (Note, some wallets combine both sets of capabilities, but for simplicity's sake, our sample implementation treats them as distinct and independent applications.)
Some things to note:
challengeTokenUrl
property.did:pkh
, did:web
or did:key
)credentialSubject.id
s of the presented VCs, thus verifying both liveness and control of the identifier against which the credentials were issued.reply_url
property).In this example, a user wants to verify address-bound credentials issued to a blockchain address. Since these credentials simplify the trust model, they only need a fresh, live signature from the cryptocurrency wallet's private key to authenticate the session in which those credentials are presented, rather than a signature over the credential themselves. The credentials do not necessarily need to be stored in an identity wallet or even in a crypto wallet, since the crypto wallet will need to be authenticated to present them and they are already tamper-proofed.
reply_url
property).