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

Add initial VC API Exchanges docs. #50

Merged
merged 12 commits into from
Sep 12, 2024
174 changes: 174 additions & 0 deletions developers/wallets/exchanges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
layout: subpage
title: "Handling a VC API Exchange in a Web Wallet"
permalink: /developers/wallets/exchanges/
---

## {{ title }}

> A VC API workflow defines a particular set of steps for exchanging verifiable
> credentials between two parties across a trust boundary. Each step can involve
> the issuance, verification, transmission, or presentation of verifiable
> credentials.
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved

A Web Wallet may receive an Exchange URL through CHAPI, reading a QR code, or
via some other user initiated transmission.

Once that URL is received, the Wallet can initiate the exchange (acting as the
_exchange client_) by sending a POST request to that URL.

Exchange URL:
```
https://vcapi.example.com/exchanges/12345/
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
```

To initiate an exchange using VC API, an exchange client performs an HTTP POST
sending a JSON object as the request body. In the simplest case, when the client
has no constraints of its own on the exchange — i.e., it has nothing to request
from the other party — the JSON object is empty ({})--as seen below:

```http
POST /exchanges/12345/
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
Host: vcapi.example.com

{}
```

The workflow service then responds with its own JSON object in the response
body:

```json
{}
```

If the response object is empty (as above), the exchange is complete and nothing
is requested from nor offered to the exchange client.

If, however, the object includes `verifiablePresentationRequest`, then the
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
exchange is not yet complete and some *additional information is requested*, as
specified by the contents of the associated verifiable presentation request.

For example:
```json
{
"verifiablePresentationRequest": {
"query": [{
"type": "QueryByExample",
"credentialQuery": [{
"reason": "Please present proof of citizenship.",
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
"example": {
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v1"
],
"type": "PermanentResidentCard"
}
}]
}]
}
}
```

If the object includes `verifiablePresentation`, then some *information is
offered*, such as verifiable credentials issued to the holder operating the
exchange client (i.e. the Wallet) or verifiable credentials with information
about the exchange server's operator based on the exchange client's request.

For example:
```json
{
"verifiablePresentation": {
"@context": [
"https://www.w3.org/ns/credentials/v2"
],
"type": ["VerifiablePresentation"],
"verifiableCredential": [{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v1"
],
"type": ["VerifiableCredential", "PermanentResidentCard"],
// additional properties...
}]
}
}
```

If the object includes `redirectUrl`, the *exchange is complete* and the
workflow service recommends that the client proceed to another place to continue
the interaction in another form.

For example:
```json
{
"redirectUrl": "https://vcapi.example.com/go-here-next/"
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
}
```

Many Verifiable Credential use cases can be implemented using these basic
primitives. Either party to an exchange is capable of requesting Verifiable
Presentations and of providing one or more Verifiable Credentials that might be
necessary to establish trust and/or gain authorization capabilities, and either
party is capable of presenting credentials that they hold or that they have
issued. Specific workflows can be configured to expect specific presentations
and credentials and to reject deviations from the expected flow of information.

When a workflow service determines that a particular message is not acceptable,
it raises an error by responding with a `4xx` HTTP status message and a JSON
object that expresses information about the error.

Below is an example of a typical exchange:

```mermaid
sequenceDiagram
participant H as Holder
participant W as Holder Coordinator (Wallet)
participant I as Issuer/Verifier Coordinator
autonumber
Note right of H: Start exchange
W->>I: Initiate
Note right of W: POST /workflows/123/exchanges/123 — HTTP request to start exchange (e.g., send credentials, get credentials)
I->>W: Verifiable Presentation Request (VPR)
Note left of I: VPR includes method of interaction, for purposes of exchange
W->>I: Verifiable Presentation (VP)
Note right of W: POST /workflows/123/exchanges/abc — sent via interaction mechanism to meet requirements of exchange
I->>W: Verifiable Presentation
Note left of I: VP includes result of exchange (e.g., VCs), or VPR with new interaction request, or error description
```

The exchange client (Wallet) code for a flow like the above may look similar to
the following:

```js
const receivedExchangeUrl = 'https://vcapi.example.com/workflows/123/exchanges/123';
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved

const response = await fetch(receivedExchangeUrl, {
method: 'POST'
body: JSON.stringify({})
});
const body = response.json();
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved

function checkResponse(body) {
if('verifiablePresentationRequest' in body) {
// use the information in the Verifiable Presentation Request to find a
// credentail that fullfills the request, then send a Verifiable
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
// Presentation as the response to the interaction endpoint included in the
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
// Verifiable Presentation Request
const presentation = findCredentialAndCreatePresentation();
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
// TODO: properly extract interaction URL
const interactionUrl = body.interact.service[0].serviceEndpoint;
const response = await fetch(interactionUrl, {
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
method: 'POST',
body: JSON.stringify(presentation)
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
});
checkResponse(response.json());
}
// TODO: should these be exclusive?
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
if('verifiablePresentation' in body) {
// the Wallet has received a Verifiable Presentation containing one or more
// Verifiable Credentials--validate and verify them per your use case
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
}
if('redirectUrl' in body) {
// TODO: take the user to the new location OR does the exchange "move"?
BigBlueHat marked this conversation as resolved.
Show resolved Hide resolved
}
}
1 change: 1 addition & 0 deletions developers/wallets/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ CHAPI integrates easily into digital wallet software, allowing your wallet to re
* [Verifiable Credential Storage](#verifiable-credential-storage)
* [Verifiable Credential Presentation](#verifiable-credential-presentation)
* [DID Authentication with CHAPI](#did-authentication-with-chapi)
* <span class="ui green tiny label">new!</span> [Handling VC API Exchanges](exchanges/)

## Native Wallets
* [Wallet Registration](native/#wallet-registration)
Expand Down