Issue Credentials

This section demonstrates how issuer1 issues a credential to user1.

First, there is some issuer initialization which must be performed.

Issuer initialization

There are three steps required in order to initialize an issuer.

  1. Onboard the issuer as a trust anchor

    Onboarding an issuer as a trust anchor is required in order to grant permission to the issuer to write to the ledger. Both creating a credential schema and credential definition as described below require writing to the ledger.

    The following command on-boards issuer1 as a trust anchor:

    curl -u issuer1:issuer1pw -X PATCH -d '{"role": "TRUST_ANCHOR"}' $URL/api/v1/agents/issuer1 -H 'Content-Type: application/json'

  2. Create a credential schema or get the DID of an existing credential schema

    A credential schema consists of a list of attribute names. It is written to the ledger and may be shared by multiple issuers.

    For example, suppose a credential schema which is used to issue job employment credentials has the following attribute names: name, employeeId, department, and dateOfHire. This credential schema could be used by multiple corporate issuers to issue job employment credentials to their employees.

    In this tutorial, issuer1 creates its own credential schema as follows: curl -u issuer1:issuer1pw -X POST -d '{"name":"cred_schema1", "version": "1.0", "attrs": ["attr1", "attr2", "attr3"]}' $URL/api/v1/credential_schemas -H 'Content-Type: application/json' The names of the attributes in this schema are simply attr1, attr2, and attr3. The 'id' value in the response is referred to as the <schema_id> in the next step.

  3. Create a credential definition

    A credential definition is used by an issuer to issue credentials. It uniquely identifies both the agent which issues the credential and also the attributes which are in the credential. In other words, the credential schema is a template for issuing credentials whereas a credential definition is an instance of that template which is used by a single agent.

    Issuer1 creates a credential definition associated with the credential schema, where <schema_id> is the 'id' value from the response received in the previous step. curl -u issuer1:issuer1pw -X POST -d '{"schema_id":"<schema_id>"}' $URL/api/v1/credential_definitions -H 'Content-Type: application/json'

Now that issuer initialization is complete, let's have issuer1 issue a credential to user1.

There are two types or issuance flows supported: issuer-initiated and user-initiated.

Issuer-initiated issuance

Issuer1 sends a credential offer to user1 by specifying the credential schema and version as follows:

curl -u issuer1:issuer1pw -X POST -d '{"to": {"name": "user1"}, "schema_name": "cred_schema1", "schema_version": "1.0", "attributes": {"attr1": "attr1Val", "attr2": "attr2Val", "attr3": "10"}}' $URL/api/v1/credentials -H 'Content-Type: application/json'

Similarly, issuer1 can send a credential offer to user1 by specifying the credential definition ID as follows:

curl -u issuer1:issuer1pw -X POST -d '{"to": {"name": "user1"}, "credential_definition_id": "<cred_def_id>", "attributes": {"attr1": "attr1Val", "attr2": "attr2Val", "attr3": 10}}' $URL/api/v1/credentials -H 'Content-Type: application/json'

The "to" value of the body of the request identifies the agent to which the credential offer is being sent. In the examples above, the "name" of the agent is specified but this option is only valid when communicating between two agents in the same account. In order to communicate between two agents in different accounts, you must use the DID or URL options as follows:

  1. By DID

    Assuming is the value of the remote.public.did, remote.pairwise.did, or local.pairwise.did of the connection to user1 you may use {"to": {"did": "<did>"}}.

  2. By URL

    Assuming is the agent URL of the user1 you may use {"to": {"url": "<agent-URL>"}}

Now that issuer1 has made the credential offer, user1 views all credential offers as follows:

curl -u user1:user1pw $URL/api/v1/credentials?state=inbound_offer

This lists all credentials whose state if inbound_offer, where each credential has a unique id field value referred to as <id> below.

Or you can view a specific credential offer as follows, where <id> is the id field of the credential.

curl -u user1:user1pw $URL/api/v1/credentials/<id>

In either case, user1 views the offer.attributes section to see if it agrees with the attribute values being offered.

Assuming that user1 agrees with the attribute values, user1 accepts the credential offer as follows. Note that you must replace <id> with the value from the id field.

curl -u user1:user1pw -X PATCH -d '{"state":"accepted"}' $URL/api/v1/credentials/<id> -H 'Content-Type: application/json'

This results in a credential state of 'stored' for user1.

And it also results in a credential state of issued for issuer1 which can be viewed as follows:

curl -u issuer1:issuer1pw $URL/api/v1/credentials/<id>

If user1 did not agree with the attribute values or just did not want to accept the credential offer for some other reason, there are two options:

  1. Reject the credential offer

    The following retains the credential object but changes its state to "rejected" for both user1 and issuer1: curl -u user1:user1pw -X PATCH -d '{"state":"rejected"}' $URL/api/v1/credentials/<id> -H 'Content-Type: application/json'

  2. Delete the credential offer

    The following deletes the credential object for user1 and changes the state of the credential object to "deleted" for issuer1: curl -u user1:user1pw -X DELETE $URL/api/v1/credentials/<id>

User-initiated issuance

The user-initiated issuance flow is similar to the issuer-initiated issuance flow except that it begins with an additional step: the user sends a credential request to the issuer, asking the issuer to create a credential offer.

User1 sends a credential request to issuer1

curl -u user1:user1pw -X POST -d '{"state": "outbound_request", "to": {"name": "issuer1"}, "schema_name": "cred_schema1", "schema_version": "1.0"}' $URL/api/v1/credentials -H 'Content-Type: application/json'

Issuer1 views all inbound credential requests and finds the one from user1, taking note of its id.

curl -u issuer1:issuer1pw $URL/api/v1/credentials?state=inbound_request

Issuer1 issues a credential offer to user1 based on its request, where <id> is the id value from the previous step.

curl -u issuer1:issuer1pw -X PATCH -d '{"state": "outbound_offer", "attributes": {"attr1": "attr1Val", "attr2": "attr2Val", "attr3": "10"}}' $URL/api/v1/credentials/<id> -H 'Content-Type: application/json'

From this point forward, the user-initiated issuance flow is identical to that of the issuer-initiated issuance flow.

User1 views all credential offers as follows:

curl -u user1:user1pw $URL/api/v1/credentials?state=inbound_offer

Or views this specific credential offer as follows:

curl -u user1:user1pw $URL/api/v1/credentials/<id>

In either case, user1 views the offer.attributes section to see the attribute values being offered.

User1 accepts the credential offer. Note that this results in a credential state of 'stored' for user1.

curl -u user1:user1pw -X PATCH -d '{"state":"accepted"}' $URL/api/v1/credentials/<id> -H 'Content-Type: application/json'

And it results in a credential state of issued for issuer1 which can be viewed as follows:

curl -u issuer1:issuer1pw $URL/api/v1/credentials/<id>

Listing credentials

The credentials held by user1 can be listed as follows:

curl -u user1:user1pw $URL/api/v1/credentials

And the credentials issued by issuer1 can be listed as follows:

curl -u issuer1:issuer1pw $URL/api/v1/credentials

Deleting credentials

At this point in the tutorial, you should not delete any credentials; however, for your reference, it is easy to do.

You could delete a credential for issuer1 as follows:

curl -u issuer1:issuer1pw -X DELETE $URL/api/v1/credentials/<id>

Or similarly, you could delete a credential for user1 as follows:

curl -u user1:user1pw -X DELETE $URL/api/v1/credentials/<id>

But for now, let's use the issued credentials to perform verification.