-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add guides for connect and issue flows (#4)
- Loading branch information
abalias
committed
Feb 7, 2023
1 parent
a547964
commit 9bcc8c2
Showing
10 changed files
with
938 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
# Connections | ||
|
||
A connection is a stateful relationship between two parties that enables secure communication. | ||
|
||
The **Connection protocol** is required to establish secure connections between agents, | ||
allowing them to exchange information and interact. | ||
|
||
The protocol provides endpoints for creating and managing connections, as well as for accepting invitations. | ||
|
||
## Roles | ||
|
||
The connection protocol has two roles: | ||
|
||
1. **Inviter**: A subject that initiates a connection request by sending a *connection invitation*. | ||
2. **Invitee**: A subject that receives a connection invitation and accepts it by sending a *connection request*. | ||
|
||
## Prerequisites | ||
|
||
1. **Inviter** and **Invitee** PRISM Agents up and running | ||
|
||
## PRISM Agent endpoints overview | ||
|
||
The protocol uses the following REST API endpoints: | ||
|
||
1. [`/connections`](/agent-api/#tag/Connections-Management): | ||
- [`POST`](/agent-api/#tag/Connections-Management/operation/createConnection): Creates a new connection and returns an invitation | ||
- [`GET`](/agent-api/#tag/Connections-Management/operation/getConnections): Returns a list of connections | ||
2. [`GET /connections/{connectionId}`](/agent-api/#tag/Connections-Management/operation/getConnection): Returns an existing connection record by id | ||
3. [`POST /connection-invitations`](/agent-api/#tag/Connections-Management/operation/acceptConnectionInvitation): Accepts an externally received invitation | ||
|
||
:::info | ||
For more detailed information, please, check the full **[PRISM Agent API](/agent-api).** | ||
::: | ||
|
||
## Inviter Flow | ||
|
||
1. Generate and share a new Out-of-Band (OOB) invitation (connection is created in `InvitationGenerated` state) | ||
2. Receive a connection request from the **Invitee** (connection is moved to `ConnectionRequestReceived` state) | ||
3. Accept the connection request (connection is moved to `ConnectionResponsePending` state) | ||
4. Send the connection response via the DIDComm Agent (connection achieves `ConnectionResponseSent` state) | ||
|
||
The **Inviter**'s state transitions are represented by the following Mermaid diagram: | ||
```mermaid | ||
--- | ||
title: Inviter Connection State | ||
--- | ||
stateDiagram-v2 | ||
[*] --> InvitationGenerated: generate and share new OOB invitation | ||
InvitationGenerated --> ConnectionRequestReceived: receive connection request | ||
ConnectionRequestReceived --> ConnectionResponsePending: accept connection request | ||
ConnectionResponsePending --> ConnectionResponseSent: send connection response (DIDComm) | ||
ConnectionResponseSent --> [*] | ||
``` | ||
|
||
|
||
## Invitee Flow | ||
|
||
1. Receive the OOB invitation (`InvitationReceived` state) | ||
2. Accept the invitation (connection is created in `ConnectionRequestPending` state) | ||
3. Send the connection request via DIDComm (connection achieves `ConnectionRequestSent` state) | ||
4. Receive the connection response (connection achieves `ConnectionResponseReceived` state) | ||
|
||
The **Invitee**'s state transitions are represented by the following Mermaid diagram: | ||
```mermaid | ||
--- | ||
title: Invitee Connection State | ||
--- | ||
stateDiagram-v2 | ||
[*] --> InvitationReceived: receive OOB invitation | ||
InvitationReceived --> ConnectionRequestPending: accept invitation | ||
ConnectionRequestPending --> ConnectionRequestSent: send connection request (DIDComm) | ||
ConnectionRequestSent --> ConnectionResponseReceived: receive connection response | ||
ConnectionResponseReceived --> [*] | ||
``` | ||
|
||
## Command line example | ||
|
||
The following example demonstrates on how you could use two PRISM Agents API to set up connection between them. | ||
|
||
### **Inviter** creates an invitation | ||
|
||
```shell | ||
curl -X 'POST' \ | ||
'http://localhost:8080/prism-agent/connections' \ | ||
-H 'Content-Type: application/json' \ | ||
-d '{ "label": "Connect with Alice" }' | jq | ||
``` | ||
|
||
Example response: | ||
```json | ||
{ | ||
"connectionId": "1893e207-4cba-4792-8179-067c78d2acc2", | ||
"createdAt": "2023-02-02T17:14:13.593647Z", | ||
"invitation": { | ||
"from": "did:peer:inviter-did", | ||
"id": "1893e207-4cba-4792-8179-067c78d2acc2", | ||
"invitationUrl": "https://domain.com/path?_oob={RAW_INVITATION}", | ||
"type": "https://didcomm.org/out-of-band/2.0/invitation" | ||
}, | ||
"kind": "/connections/1893e207-4cba-4792-8179-067c78d2acc2", | ||
"label": "Connect with Alice", | ||
"self": "Connection", | ||
"state": "InvitationGenerated" | ||
} | ||
``` | ||
|
||
### **Invitee** accepts OOB invitation | ||
|
||
Replace `{RAW_INVITATION}` with the value of the '_oob' query string parameter from the invitation URL above | ||
```shell | ||
curl -X 'POST' \ | ||
'http://localhost:8090/prism-agent/connection-invitations' \ | ||
-H 'Content-Type: application/json' \ | ||
-d '{ "invitation": "{RAW_INVITATION}" }' | jq | ||
``` | ||
|
||
Example response: | ||
```json | ||
{ | ||
"connectionId": "755a457a-878e-4292-a3f2-cb83601f802e", | ||
"createdAt": "2023-02-02T18:05:58Z", | ||
"invitation": { | ||
"from": "did:peer:inviter-did", | ||
"id": "1893e207-4cba-4792-8179-067c78d2acc2", | ||
"invitationUrl": "https://domain.com/path?_oob={RAW_INVITATION}", | ||
"type": "https://didcomm.org/out-of-band/2.0/invitation" | ||
}, | ||
"kind": "/connections/755a457a-878e-4292-a3f2-cb83601f802e", | ||
"myDid": "did:peer:invitee-did", | ||
"self": "Connection", | ||
"state": "ConnectionRequestPending", | ||
"theirDid": "did:peer:inviter-did", | ||
"updatedAt": "2023-02-02T18:05:59Z" | ||
} | ||
``` | ||
|
||
### **Invitee** retrieves the list of connections | ||
|
||
```shell | ||
curl -X 'GET' 'http://localhost:8090/prism-agent/connections' | jq | ||
``` | ||
|
||
Example output: | ||
```json | ||
{ | ||
"contents": [ | ||
{ | ||
"connectionId": "755a457a-878e-4292-a3f2-cb83601f802e", | ||
"createdAt": "2023-02-02T18:05:58Z", | ||
"invitation": { | ||
"from": "did:peer:issuer-did", | ||
"id": "1893e207-4cba-4792-8179-067c78d2acc2", | ||
"invitationUrl": "https://domain.com/path?_oob={RAW_INVITATION}", | ||
"type": "https://didcomm.org/out-of-band/2.0/invitation" | ||
}, | ||
"kind": "/connections/755a457a-878e-4292-a3f2-cb83601f802e", | ||
"myDid": "did:peer:holder-did", | ||
"self": "Connection", | ||
"state": "ConnectionResponseReceived", | ||
"theirDid": "did:peer:issuer-did", | ||
"updatedAt": "2023-02-02T18:06:14Z" | ||
} | ||
], | ||
"kind": "Collection", | ||
"self": "/collections" | ||
} | ||
``` | ||
|
||
### **Inviter** retrieves the list of connections | ||
|
||
```shell | ||
curl -X 'GET' 'http://localhost:8080/prism-agent/connections' | jq | ||
``` | ||
|
||
Example response: | ||
```json | ||
{ | ||
"contents": [ | ||
{ | ||
"connectionId": "1893e207-4cba-4792-8179-067c78d2acc2", | ||
"createdAt": "2023-02-02T17:14:13Z", | ||
"invitation": { | ||
"from": "did:peer:issuer-did", | ||
"id": "1893e207-4cba-4792-8179-067c78d2acc2", | ||
"invitationUrl": "https://domain.com/path?_oob={RAW_INVITATION}", | ||
"type": "https://didcomm.org/out-of-band/2.0/invitation" | ||
}, | ||
"kind": "/connections/1893e207-4cba-4792-8179-067c78d2acc2", | ||
"label": "Connect with Alice", | ||
"myDid": "did:peer:issuer-did", | ||
"self": "Connection", | ||
"state": "ConnectionResponseSent", | ||
"theirDid": "did:peer:holder-did", | ||
"updatedAt": "2023-02-02T18:06:16Z" | ||
} | ||
], | ||
"kind": "Collection", | ||
"self": "/collections" | ||
} | ||
``` | ||
|
||
:::info | ||
For more detailed information, please, check the full **[PRISM Agent API](/agent-api).** | ||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,176 @@ | ||
# Issue credential | ||
# Issue Credentials | ||
|
||
In Atala PRISM, the **Issue Credentials Protocol** allows you to create, retrieve, and manage issued verifiable credentials (VCs) between a VC issuer and a VC holder. | ||
|
||
## Roles | ||
|
||
In the **Issue Credentials Protocol**, there are two roles: | ||
|
||
1. **Issuer** is responsible for creating a new credential offer, sending it to a **Holder**, and issuing the VC once the offer is accepted. | ||
2. **Holder** is responsible for accepting a credential offer from an issuer and receiving the VC. | ||
|
||
The **Issuer** and **Holder** interact with the **PRISM Agent API** to perform the operations defined in the protocol. | ||
|
||
|
||
## Prerequisites | ||
|
||
Before using the **Issuing Credentials protocol**, the following conditions must be present: | ||
|
||
1. **Issuer** and **Holder** PRISM Agents up and running | ||
2. A connection must be established between the **Issuer** and **Holder** PRISM Agents (see [Connections](../connections/connection.md)) | ||
|
||
## Overview | ||
|
||
The protocol described is a VC issuance process between two Atala PRISM Agents, the **Issuer** and the **Holder**. | ||
|
||
The protocol consists of the following main parts: | ||
|
||
1. The **Issuer** creates a new credential offer using the [`/issue-credentials/credential-offers`](/agent-api/#tag/Issue-Credentials-Protocol/operation/createCredentialOffer) endpoint, which includes information such as the schema identifier and claims. | ||
2. The **Holder** can then retrieve the offer using the [`/issue-credentials/records`](/agent-api/#tag/Issue-Credentials-Protocol/operation/getCredentialRecords) endpoint and accept the offer using the [`/issue-credentials/records/{recordId}/accept-offer`](/agent-api/#tag/Issue-Credentials-Protocol/operation/acceptCredentialOffer) endpoint. | ||
3. The **Issuer** then uses the [`/issue-credentials/records/{recordId}/issue-credential`](/agent-api/#tag/Issue-Credentials-Protocol/operation/issueCredential) endpoint to issue the credential, which gets sent to the Holder via DIDComm. The Holder receives the credential, and the protocol is complete. | ||
|
||
The schema identifier defines the structure and the credential type issued, | ||
while the claims provide specific information about the individual, such as their name or qualifications. | ||
|
||
This protocol is applicable in various real-life scenarios, such as educational credentialing, employment verification, and more. | ||
In these scenarios, the **Issuer** could be a school, an employer, etc., and the **Holder** could be a student or an employee. | ||
The VCs issued during this protocol could represent a diploma, a certificate of employment, etc. | ||
|
||
## Endpoints | ||
|
||
| Endpoint | Description | Role | | ||
| --- | --- | --- | | ||
| [`/issue-credentials/credential-offers`](/agent-api/#tag/Issue-Credentials-Protocol/operation/createCredentialOffer) | This endpoint allows you to create a new credential offer | Issuer | | ||
| [`/issue-credentials/records`](/agent-api/#tag/Issue-Credentials-Protocol/operation/getCredentialRecords) | This endpoint allows you to retrieve a collection of all the existing credential records | Issuer, Holder | | ||
| [`/issue-credentials/records/{recordId}`](/agent-api/#tag/Issue-Credentials-Protocol/operation/getCredentialRecord) | This endpoint allows you to retrieve a specific credential record by its `id` | Issuer, Holder | | ||
| [`/issue-credentials/records/{recordId}/accept-offer`](/agent-api/#tag/Issue-Credentials-Protocol/operation/acceptCredentialOffer) | This endpoint allows you to accept a credential offer | Holder | | ||
| [`/issue-credentials/records/{recordId}/issue-credential`](/agent-api/#tag/Issue-Credentials-Protocol/operation/issueCredential) | This endpoint allows you to issue a VC for a specific credential record. | Issuer | | ||
|
||
|
||
:::info | ||
For more detailed information, please, check the full **[PRISM Agent API](/agent-api).** | ||
::: | ||
|
||
## Issuer interactions | ||
|
||
This section describes the Issuer role's available interactions with the PRISM Agent. | ||
|
||
### Creating a Credential Offer | ||
|
||
To start the process, the issuer needs to create a credential offer. | ||
To do this, make a `POST` request to the [`/issue-credentials/credential-offers`](/agent-api/#tag/Issue-Credentials-Protocol/operation/createCredentialOffer) endpoint with a JSON payload that includes the following information: | ||
|
||
1. `subjectId`: This field represents the unique identifier for the subject of the verifiable credential. It is a DID (Decentralized Identifier) string, such as `did:prism:subjectIdentifier`. | ||
2. `schemaId`: This is an identifier for a schema, which defines the structure and format of the data in a verifiable credential. The schema identifier must be unique and typically a URL or a URN. | ||
3. `claims`: The data stored in a verifiable credential. Claims get expressed in a key-value format and must conform to the structure and format defined in the schema. The claims contain the data that the issuer attests to, such as name, address, date of birth, and so on. | ||
|
||
Once the request initiates, a new credential record for the issuer gets created with a unique ID. The state of this record is now `OfferPending`. | ||
|
||
```shell | ||
# Issuer POST request to create a new credential offer | ||
curl -X 'POST' \ | ||
'http://localhost:8080/prism-agent/issue-credentials/credential-offers' \ | ||
-H 'accept: application/json' \ | ||
-H 'Content-Type: application/json' \ | ||
-d '{ | ||
"schemaId": "schema:1234", | ||
"subjectId": "did:prism:subjectIdentifier", | ||
"claims": { | ||
"firstname": "Alice", | ||
"lastname": "Wonderland", | ||
"birthdate": "01/01/2000" | ||
} | ||
}' | ||
``` | ||
|
||
### Sending the Offer to the Holder | ||
|
||
The next step for the **Issuer** is to send the offer to the holder using DIDComm. | ||
To do this, the **Issuer** agent will process the offer and send it to the holder agent. | ||
This process is automatic. The state of the **Issuer**'s record will change to `OfferSent`. | ||
|
||
### Issuing the Credential | ||
|
||
Once the holder has approved the offer and sent a request to the **Issuer**, | ||
the **Issuer** will receive the request via DIDComm and update the state of the record to `RequestReceived.` | ||
|
||
The **Issuer** can then use the [`/issue-credentials/records/{recordId}/issue-credential`](/agent-api/#tag/Issue-Credentials-Protocol/operation/issueCredential) endpoint to issue the credential to the holder. | ||
|
||
```shell | ||
# Issuer POST request to issue the credential | ||
# make sure you have `issuer_record_id` extracted from created credential offer | ||
# and the record achieved `RequestReceived` state | ||
curl -X POST \ | ||
"http://localhost:8080/prism-agent/issue-credentials/records/$issuer_record_id/issue-credential" \ | ||
-H "Content-Type: application/json" | ||
``` | ||
|
||
When this endpoint gets called, the state of the record will change to `CredentialPending,` and after processing, it will change to `CredentialGenerated.` | ||
|
||
Finally, the **Issuer** agent will send the credential to the holder via DIDComm, | ||
and the state of the record will change to `CredentialSent`. | ||
At this point, the **Issuer**'s interactions with the holder are complete. | ||
|
||
```mermaid | ||
--- | ||
title: Issuer flow | ||
--- | ||
stateDiagram-v2 | ||
[*] --> OfferPending: create credential offer (`/issue-credentials/credential-offers`) | ||
OfferPending --> OfferSent: send offer (auto via PRISM Agent DIDComm) | ||
OfferSent --> RequestReceived: receive request (auto via PRISM Agent DIDComm) | ||
RequestReceived --> CredentialPending: issue credential (`/issue-credentials/records/{recordId}/issue-credential`) | ||
CredentialPending --> CredentialGenerated: process issued credential (auto via PRISM Agent) | ||
CredentialGenerated --> CredentialSent: send credential (auto via PRISM Agent) | ||
``` | ||
|
||
## Holder interactions | ||
|
||
This section describes the Holder role's available interactions with the PRISM Agent. | ||
|
||
### Receiving the VC Offer | ||
|
||
The **Holder** will receive the offer from the **Issuer** via DIDComm, | ||
and a new credential record with a unique ID will be created in the `OfferReceived` state. | ||
|
||
This process is automatic for the PRISM Agent. | ||
|
||
You could check if a new credential offer is available using [`/issue-credentials/records`](/#tag/Issue-Credentials-Protocol/operation/getCredentialRecords) request and check for any records available in `OfferReceived` state: | ||
```shell | ||
# Holder GET request to retrieve credential records | ||
curl "http://localhost:8090/prism-agent/issue-credentials/records" \ | ||
-H "Content-Type: application/json" | ||
``` | ||
|
||
|
||
### Approving the VC Offer | ||
|
||
To accept the offer, the **Holder** can make a `POST` request to the [`/issue-credentials/records/{recordId}/accept-offer`](/agent-api/#tag/Issue-Credentials-Protocol/operation/acceptCredentialOffer) endpoint: | ||
```shell | ||
# Holder POST request to accept the credential offer | ||
curl -X POST "http://localhost:8090/prism-agent/issue-credentials/records/$holder_record_id/accept-offer" \ | ||
-H "Content-Type: application/json" | ||
``` | ||
|
||
This request will change the state of the record to `RequestPending`. | ||
|
||
### Receiving the VC Credential | ||
|
||
Once the **Holder** has approved the offer and sent a request to the **Issuer**, the **Holder** agent will process the request and send it to the **Issuer** agent. | ||
The state of the **Holder**'s record will change to `RequestSent`. | ||
|
||
After the **Issuer** has issued the credential, the **Holder** will receive the credential via DIDComm, and the state of the **Holder**'s record will change to `CredentialReceived`. | ||
This process is automatic for the PRISM Agent. | ||
|
||
**Holder** can check the achieved credential using a GET request to [`/issue-credentials/records/{recordId}/`](/agent-api/#tag/Issue-Credentials-Protocol/operation/getCredentialRecord) endpoint. | ||
|
||
```mermaid | ||
--- | ||
title: Holder Flow | ||
--- | ||
stateDiagram-v2 | ||
[*] --> OfferReceived: receive offer (auto via PRISM Agent) | ||
OfferReceived --> RequestPending: accept offer (`/issue-credentials/records/{recordId}/accept-offer`) | ||
RequestPending --> RequestSent: send request (auto via PRISM Agent) | ||
RequestSent --> CredentialReceived: receive credential (auto via PRISM Agent) | ||
``` |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.