Skip to content

Commit

Permalink
Improve Verifiable Credential docs (#2719)
Browse files Browse the repository at this point in the history
* Improve VC docs

* Typo correction

---------

Co-authored-by: Andri Schatz <[email protected]>
  • Loading branch information
lmuntaner and LXIF authored Dec 2, 2024
1 parent f175bdb commit d9e8e2a
Showing 1 changed file with 63 additions and 56 deletions.
119 changes: 63 additions & 56 deletions docs/vc-spec.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# II Verifiable Credential Spec (MVP)


## Issuer API

This section describes the (Candid) interface to be implemented by an issuer of verifiable credentials on the IC.
Expand Down Expand Up @@ -95,15 +94,15 @@ service: {
In the attribute sharing flow a user must approve the issuance of a verifiable
credential by an issuer, and this happens by approving a human-readable consent message from the issuer.

Identity provider uses a VC-extension of [ICRC-21](https://github.com/dfinity/wg-identity-authentication/blob/main/topics/icrc_21_consent_msg.md), and requests the consent message via `Icrc21VcConsentMessageRequest`,
Identity provider uses a VC-extension of [ICRC-21](https://github.com/dfinity/wg-identity-authentication/blob/main/topics/icrc_21_consent_msg.md), and requests the consent message via `Icrc21VcConsentMessageRequest`,
Upon successful response identity provider displays the consent message from `Icrc21ConsentInfo` to the user.

### 2: Derivation Origin

The issuer must implement also `derivation_origin`-API, which allows for taking the advantage
of the [Alternative Derivation Origins](https://internetcomputer.org/docs/current/references/ii-spec#alternative-frontend-origins)-feature.
`derivation_origin` is called by the identity provider to obtain an URL to be used as the derivation origin
for user's principal. If an issuer doesn't use the _Alternative Derivation Origins_-feature,
for user's principal. If an issuer doesn't use the _Alternative Derivation Origins_-feature,
the function should return just the default value, namely the canister's URL: `https://<issuer-canister-id>.icp0.io`.

```candid
Expand Down Expand Up @@ -156,19 +155,22 @@ type ArgumentValue = variant { "Int" : int32; String : text };

Specifically, the issuer checks via `signed_id_alias.credential_jws` that user identified by its `sub` claim on the
issuer side has a valid `has_id_alias` principal for the purpose of attribute sharing, and that the credential
described by `credential_spec` does apply to the `caller`. When these checks are successful, the issuer
prepares and returns a context in `PreparedCredentialData.prepared_context` (if any). The returned prepared context is then
described by `credential_spec` does apply to the `caller`. When these checks are successful, the issuer
prepares and returns a context in `PreparedCredentialData.prepared_context` (if any). The returned prepared context is then
passed back to the issuer in a subsequent `get_credential`-call (see below).
This call must be authenticated, i.e. the sender must match the principal for which the credential is requested.

**NOTE:**
The value of `prepared_context` is basically used to transfer information between `prepare_credential`
and `get_credential` steps, and it is totally up to the issuer to decide on the content of
that field. That is, the issuer creates `prepared_context`, and is the only entity that
consumes it. For example, when using [canister signatures](https://internetcomputer.org/docs/current/references/ic-interface-spec#canister-signatures)
that field. That is, the issuer creates `prepared_context`, and is the only entity that
consumes it. For example, when using [canister signatures](https://internetcomputer.org/docs/current/references/ic-interface-spec#canister-signatures)
the context contains a time-stamped yet unsigned VC, for which the canister signature will be
available only at `get_credential`-call.

**NOTE:**
The signed credential must use the verifiable credential domain separator `"iccs_verifiable_credential"` as an array of bytes.

### 4: Get Credential

`get_credential`-service issues the actual credential requested by the user.
Expand All @@ -188,7 +190,7 @@ type IssuedCredentialData = record { vc_jws : text };
```

`GetCredentialRequest` should contain the same parameters as `PrepareCredentialRequest`, plus the
`prepared_context`-value returned by `prepare_credential`, if any.
`prepared_context`-value returned by `prepare_credential`, if any.
The issuer performs the same checks as during the `prepare_credential`-call,
plus verify that `prepared_context` is consistent with the other parameters.
This call must be authenticated, i.e. the sender must match the principal for which the credential is requested.
Expand All @@ -198,10 +200,11 @@ Upon successful checks, issuer returns the signed credential in JWS-format.
### Recommended convention connecting credential specification with the returned credentials.

Service discovery and syntax of the claims in the returned credentials are out of scope
of this spec (of the MVP service). However, an issuer may follow the convention below,
of this spec (of the MVP service). However, an issuer may follow the convention below,
for an easier verification of the returned credentials.

Given a credential spec like

```json
"credentialSpec": {
"credentialType": "SomeVerifiedProperty",
Expand All @@ -210,9 +213,11 @@ Given a credential spec like
"another_argument": 42,
}
```

the returned JWT should contain in `credentialSubject` a property
named by the value of `credentialType` from the spec, with key-value
entries listing the arguments from the spec, namely

```json
"SomeVerifiedProperty": {
"argument_1": "value_1",
Expand All @@ -221,21 +226,24 @@ entries listing the arguments from the spec, namely
```

For example, for `VerifiedAdult`-credential we'd use the following credential spec

```json
"credentialSpec": {
"credentialType": "VerifiedAdult",
"arguments": {
"minAge": 18,
}
```

and a compliant issuer would issue a VC that contains `credentialSubject` with the property

```json
"VerifiedAdult": {
"minAge": 18,
}
```

## Identity Provider API
## Identity Provider API

This section describes the [_`window.postMessage()`_](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)-interface implemented by the identity provider (Internet Identity).
This interface is used by a Relying Party during attribute sharing flow (cf. [flow description](https://github.com/dfinity/wg-identity-authentication/blob/main/topics/attribute-sharing.md))
Expand All @@ -256,17 +264,18 @@ After opening the II window, II will load and notify `window.opener` with the fo
### 2: Request a VC

After receiving the notification that II is ready, the relying party can request a VC by sending the following JSON-RPC request:
* Method: `request_credential`
* Params:
* `issuer`: An issuer that the relying party trusts. It has the following properties:
* `origin`: The front-end origin of the issuer. If this value is different from the value returned from the `derivation_origin` canister call, then the `origin` must be a valid alternative origin as per the [Alternative Frontend Origins](https://internetcomputer.org/docs/current/references/ii-spec#alternative-frontend-origins)-feature.
* `canisterId`: The canister id of the issuer canister (i.e. the one, that implements the candid issuer API as defined above).
* `credentialSpec`: The spec of the credential that the relying party wants to request from the issuer.
* `credentialType`: The type of the requested credential.
* `arguments`: (optional) A map with arguments specific to the requested credentials. It maps string keys to values that must be either strings or integers.
* `credentialSubject`: The subject of the credential as known to the relying party. Internet Identity will use this principal to ensure that the flow is completed using the matching identity.
* `derivationOrigin`: (optional) The origin that should be used for principal derivation (instead of the client origin) during the verification of `credentialSubject` (applicable if the relying party
uses the [Alternative Frontend Origins](https://internetcomputer.org/docs/current/references/ii-spec#alternative-frontend-origins)-feature).

- Method: `request_credential`
- Params:
- `issuer`: An issuer that the relying party trusts. It has the following properties:
- `origin`: The front-end origin of the issuer. If this value is different from the value returned from the `derivation_origin` canister call, then the `origin` must be a valid alternative origin as per the [Alternative Frontend Origins](https://internetcomputer.org/docs/current/references/ii-spec#alternative-frontend-origins)-feature.
- `canisterId`: The canister id of the issuer canister (i.e. the one, that implements the candid issuer API as defined above).
- `credentialSpec`: The spec of the credential that the relying party wants to request from the issuer.
- `credentialType`: The type of the requested credential.
- `arguments`: (optional) A map with arguments specific to the requested credentials. It maps string keys to values that must be either strings or integers.
- `credentialSubject`: The subject of the credential as known to the relying party. Internet Identity will use this principal to ensure that the flow is completed using the matching identity.
- `derivationOrigin`: (optional) The origin that should be used for principal derivation (instead of the client origin) during the verification of `credentialSubject` (applicable if the relying party
uses the [Alternative Frontend Origins](https://internetcomputer.org/docs/current/references/ii-spec#alternative-frontend-origins)-feature).

#### Examples

Expand All @@ -277,14 +286,14 @@ After receiving the notification that II is ready, the relying party can request
"method": "request_credential",
"params": {
"issuer": {
"origin": "https://employment-info.com",
"canisterId": "rwlgt-iiaaa-aaaaa-aaaaa-cai"
"origin": "https://employment-info.com",
"canisterId": "rwlgt-iiaaa-aaaaa-aaaaa-cai"
},
"credentialSpec": {
"credentialType": "VerifiedEmployee",
"arguments": {
"employerName": "XYZ Ltd."
}
"credentialType": "VerifiedEmployee",
"arguments": {
"employerName": "XYZ Ltd."
}
},
"credentialSubject": "2mdal-aedsb-hlpnv-qu3zl-ae6on-72bt5-fwha5-xzs74-5dkaz-dfywi-aqe"
}
Expand All @@ -298,14 +307,14 @@ After receiving the notification that II is ready, the relying party can request
"method": "request_credential",
"params": {
"issuer": {
"origin": "https://kyc-star.com",
"canisterId": "rdmx6-jaaaa-aaaaa-aaadq-cai"
"origin": "https://kyc-star.com",
"canisterId": "rdmx6-jaaaa-aaaaa-aaadq-cai"
},
"credentialSpec": {
"credentialType": "VerifiedAdult",
"arguments": {
"minAge": 21
}
"credentialType": "VerifiedAdult",
"arguments": {
"minAge": 21
}
},
"credentialSubject": "s33qc-ctnp5-ubyz4-kubqo-p2tem-he4ls-6j23j-hwwba-37zbl-t2lv3-pae",
"derivationOrigin": "https://vt36r-2qaaa-aaaad-aad5a-cai.icp0.io"
Expand All @@ -320,15 +329,15 @@ After receiving the notification that II is ready, the relying party can request
"method": "request_credential",
"params": {
"issuer": {
"origin": "https://kyc-resident-info.org",
"canisterId": "rwlgt-iiaaa-aaaaa-aaaaa-cai"
"origin": "https://kyc-resident-info.org",
"canisterId": "rwlgt-iiaaa-aaaaa-aaaaa-cai"
},
"credentialSpec": {
"credentialType": "VerifiedResident",
"arguments": {
"countryName": "Panama",
"countryAlpha2": "PA"
}
"credentialType": "VerifiedResident",
"arguments": {
"countryName": "Panama",
"countryAlpha2": "PA"
}
},
"credentialSubject": "cpehq-54hef-odjjt-bockl-3ldtg-jqle4-ysi5r-6bfah-v6lsa-xprdv-pqe"
}
Expand All @@ -337,14 +346,13 @@ After receiving the notification that II is ready, the relying party can request

### 3: Get a Response


#### Receive a Verifiable Presentation

After the user has successfully completed the flow, Internet Identity will respond with the following JSON-RPC response:

* `verifiablePresentation`: The JWT based verifiable presentation containing two credentials:
1. A verifiable credential issued by Internet Identity that relates the requested `credentialSubject` to another alias principal.
2. A verifiable credential issued by the requested issuer to the alias principal.
- `verifiablePresentation`: The JWT based verifiable presentation containing two credentials:
1. A verifiable credential issued by Internet Identity that relates the requested `credentialSubject` to another alias principal.
2. A verifiable credential issued by the requested issuer to the alias principal.

**NOTE:** the order of the credentials in the presentation should match the list above,
i.e. the credential that relates the subject to alias principal should come first.
Expand Down Expand Up @@ -372,24 +380,23 @@ party without impacting user's privacy.)

##### Example

``` json
```json
{
"id": 1,
"jsonrpc": "2.0",
"error": {
"version": "1",
"code": "UNKNOWN"
}
"id": 1,
"jsonrpc": "2.0",
"error": {
"version": "1",
"code": "UNKNOWN"
}
}
```


#### Interaction Model

Given the interactive nature of the flow, the relying party should not expect to receive a response immediately. Instead, the relying party should wait for one of the following events:
* II sends a JSON-RPC response as described above.
* II sends a JSON-RPC error response.
* The user closes the II window. This should be treated as an error.

The relying party may also close the II window after some timeout. The user should then be notified by the relying party that the flow failed.
- II sends a JSON-RPC response as described above.
- II sends a JSON-RPC error response.
- The user closes the II window. This should be treated as an error.

The relying party may also close the II window after some timeout. The user should then be notified by the relying party that the flow failed.

0 comments on commit d9e8e2a

Please sign in to comment.