Presentation
The IOTA DIDComm Specification is in the RFC phase and may undergo changes. Suggestions are welcome at GitHub #464.
- Version: 0.1
- Status:
IN-PROGRESS
- Last Updated: 2021-10-29
Overview
Allows presentation of one or more verifiable credentials that are issued to a holder and are uniquely presented to a third-party verifier through verifiable presentations.
Relationships
- Issuance: a presentation may be used to provide extra information from the holder during a credential issuance.
- Authentication: a presentation may be used after authentication to prove the authenticated DID is bound to a physical identity.
Example Use-Cases
- A company founder wants to prove they have a bank account in order to apply for insurance.
- A traveler proves to the border agency that they have a valid visa.
- An IoT device wants to prove who manufactured, installed, and benchmarked the device.
Roles
- Holder: possesses one or more credentials that are combined in a verifiable presentation to show proof of ownership to the verifier.
- Verifier: receives and validates the credentials presented by the holder.
Interaction
Messages
1. presentation-offer
- Type:
iota/presentation/0.1/presentation-offer
- Role: holder
Sent by the holder to offer one or more credentials for a verifier to view. CredentialInfo
is used to indicate which kinds of credentials the holder wants to present.
Structure
{
"offers": [CredentialInfo], // REQUIRED
"requireSignature": bool, // OPTIONAL
}
Field | Description | Required |
---|---|---|
offers | Array of one or more CredentialInfo , each specifying a single credential possessed by the holder.1 | ✔ |
requireSignature | Request that the verifier use a signed DIDComm message for non-repudiation of the presentation-request . The holder SHOULD issue a problem-report if the verifier does not sign the message when this is true . Default: false . | ✖ |
1 With CredentialType2021, the type
MAY be under-specified to preserve privacy but SHOULD always include the most general types. For example, a credential with the types ["VerifiableCredential", "DriversLicence", "EUDriversLicence", "GermanDriversLicence"]
could be specified as ["VerifiableCredential", "DriversLicence"]
.
Examples
- Offer a single verifiable credential:
{
"offers": [
{
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f"
}
]
}
- Offer two verifiable credentials with different issuers:
{
"offers": [
{
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f"
},
{
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/565049"
}
]
}
2. presentation-request
- Type:
iota/presentation/0.1/presentation-request
- Role: verifier
Sent by the verifier to request one or more verifiable credentials from a holder. CredentialInfo
indicates which kinds of credentials the verifier wants presented by the holder.
Verifiers are RECOMMENDED to use a signed DIDComm message. Holders may choose to blocklist verifiers that refuse to provide signed requests.
Structure
{
"requests": [{
"credentialInfo": CredentialInfo, // REQUIRED
"optional": bool // OPTIONAL
}], // REQUIRED
"challenge": string, // REQUIRED
}
Field | Description | Required |
---|---|---|
requests | Array of one or more requests, each specifying a single credential possessed by the holder. | ✔ |
credentialInfo | A CredentialInfo , specifying a credential requested by the verifier.1 | ✔ |
optional | Whether this credential is required (false ) or optional (true ) to present by the holder. A holder SHOULD send a problem report if unable to satisfy a non-optional credential request. Default: false . | ✖ |
challenge | A random string unique per presentation-request by a verifier to help mitigate replay attacks. | ✔ |
3 Verifiers are RECOMMENDED to include a proof whenever possible to avoid rejections from holders that enforce non-repudiation. Holders could use this to prove that a verifier is non-compliant with laws or regulations, e.g. over-requesting information protected by GDPR. Holders MAY still choose to accept unsigned presentation-requests
on a case-by-case basis, even if requireSignature
was true
in their presentation-offer
, as some verifiers may be unable to perform cryptographic signing operations. If the proof
is invalid, the receiving holder MUST send a problem-report
.
Examples
- Request a single credential matching both specified types using CredentialType2021.
{
"requests": [
{
"credentialInfo": {
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "UniversityDegreeCredential"]
}
}
],
"challenge": "06da6f1c-26b0-4976-915d-670b8f407f2d"
}
- Request a required credential using CredentialType2021 from a particular trusted issuer and an optional credential.
{
"requests": [
{
"credentialInfo": {
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"trustedIssuer": ["did:example:76e12ec712ebc6f1c221ebfeb1f"]
}
},
{
"credentialInfo": {
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "DriversLicence"]
},
"optional": true
}
],
"challenge": "06da6f1c-26b0-4976-915d-670b8f407f2d"
}
- Request a single credential using CredentialType2021 signed by one of several trusted issuers.
{
"requests": [
{
"credentialInfo": {
"credentialInfoType": "CredentialType2021",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"trustedIssuer": [
"did:example:76e12ec712ebc6f1c221ebfeb1f",
"did:example:f1befbe122c1f6cbe217ce21e67",
"did:example:c6ef1fe11eb22cb711e6e227fbc"
]
},
"optional": false
}
],
"challenge": "06da6f1c-26b0-4976-915d-670b8f407f2d"
}
3. presentation
- Type:
iota/presentation/0.1/presentation
- Role: holder
Sent by the holder to present a verifiable presentation of one or more verifiable credentials for a verifier to review.
Structure
{
"presentation": VerifiablePresentation // REQUIRED
}
Field | Description | Required |
---|---|---|
presentation | Signed verifiable presentation containing one or more verifiable credentials matching the presentation-request.12 | ✔ |
1 The proof
section in presentation
MUST include the challenge
sent by the verifier in the preceding presentation-request
. Revoked, disputed, or otherwise invalid presentations or credentials MUST result in a rejected presentation-result
sent back to the holder, NOT a separate [problem-report
]. Other such as the message lacking sender authenticated encryption SHOULD result in a separate [problem-report
].
2 With CredentialType2021, the included credentials SHOULD match all type
fields and one or more issuer
if included in the presentation-request
.
Examples
- Presentation of a verifiable presentation credential.
{
"presentation": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": "VerifiablePresentation",
"verifiableCredential": [{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "6c1a1477-e452-4da7-b2db-65ad0b369d1a",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f",
"issuanceDate": "2021-05-03T19:73:24Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science and Arts"
}
},
"proof": { ... }
}],
"proof": {
"challenge": "06da6f1c-26b0-4976-915d-670b8f407f2d",
...
}
}
}
4. presentation-result
- Type:
iota/presentation/0.1/presentation-result
- Role: verifier
Sent by the verifier to communicate the result of the presentation. It allows the verifier to raise disputes encountered in the verification. The message SHOULD be signed by the verifier for non-repudiation.
Similar to presentation-request
, verifiers are RECOMMENDED to use a signed DIDComm message whenever possible for non-repudiation of receipt of the presentation. Holders may choose to blocklist verifiers that refuse to provide signatures or do not send a presentation-result at all.
If the presentation-result contains disputes
or a problem report was issued, the protocol may be restarted to retry the presentation. Verifiers may choose to only request the failed credential kinds in the retry, retaining the accepted credentials from the failed presentation.
Structure
{
"accepted": bool, // REQUIRED
"disputes": [{
"credentialId": string, // REQUIRED
"dispute": Dispute, // REQUIRED
}], // OPTIONAL
}
Field | Description | Required |
---|---|---|
accepted | Indicates if the verifier accepted the presentation and credentials. | ✔ |
disputes | Array of disputes | ✖ |
credentialId | Identifier of the credential for which there is a dispute. If the credential lacks an id field, this should be a content-addressed identifier; we RECOMMEND the SHA-256 digest of the credential. | ✔ |
Examples
- Successful result:
{
"accepted": true
}
- Unsuccessful result disputing a credential's content:
{
"accepted": false,
"disputes": [{
"id": "http://example.com/credentials/123",
"dispute": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.com/credentials/123",
"type": ["VerifiableCredential", "DisputeCredential"],
"credentialSubject": {
"id": "http://example.com/credentials/245",
"currentStatus": "Disputed",
"statusReason": {
"value": "Address is out of date.",
"lang": "en"
},
},
"issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f",
"issuanceDate": "2017-12-05T14:27:42Z",
"proof": { ... }
}
}],
}
Problem Reports
The following problem-report codes may be raised in the course of this protocol and are expected to be recognised and handled in addition to any general problem-reports. Implementers may also introduce their own application-specific problem-reports.
For guidance on problem-reports and a list of general codes see problem reports.
Code | Message | Description |
---|---|---|
e.p.msg.iota.presentation.reject-offer | presentation-offer | Verifier rejects a presentation offer for any reason, e.g. unrecognised type or untrusted issuer. |
e.p.msg.iota.presentation.reject-offer.invalid-type | presentation-offer | Verifier rejects a presentation offer due to a type or @context being unsupported or otherwise invalid. |
e.p.msg.iota.presentation.reject-offer.invalid-issuer | presentation-offer | Verifier rejects a presentation offer due to issuer being unrecognised, untrusted or otherwise invalid. |
e.p.msg.iota.presentation.reject-offer.reject-require-signature | presentation-offer | Verifier rejects a presentation offer due to being unable or unwilling to provide a signature for the following presentation-request |
e.p.msg.iota.presentation.reject-request | presentation-request | Holder rejects a request for any reason. |
e.p.msg.iota.presentation.reject-request.invalid-type | presentation-request | Holder rejects a request due to a type or @context being unsupported or otherwise invalid. |
e.p.msg.iota.presentation.reject-request.invalid-issuer | presentation-request | Holder rejects a request due to a issuer being unsupported or otherwise invalid. |
e.p.msg.iota.presentation.reject-request.missing-signature | presentation-request | Holder rejects a request due to a missing signature from the verifier. The holder may choose to blocklist verifiers that fail to sign requests. |
e.p.msg.iota.presentation.reject-presentation | presentation | Verifier rejects a presentation and abandons the protocol for any reason other than disputed verifiable credential content, which should instead be communicated via presentation-result. |
e.p.msg.iota.presentation.reject-result | presentation-result | Holder rejects a result for any reason. |
e.p.msg.iota.presentation.reject-result.missing-signature | presentation-result | Holder rejects a result due to a missing signature requested from the verifier. The holder may blocklist the verifier from future requests. |
e.p.msg.iota.presentation.reject-retry | presentation-result | Holder chooses not to retry the presentation flow and terminates the protocol. |
Considerations
This section is non-normative.
- Security: implementors SHOULD transmit the presentation over an encrypted channel etc. see authentication.
- Authentication: it is RECOMMENDED to use either the authentication protocol for once-off mutual authentication or to establish sender-authenticated encryption for continuous authentication of both parties in the DIDComm thread. Signatures (
proof
fields) and signed DIDComm messages SHOULD NOT be relied upon for this in general: https://identity.foundation/didcomm-messaging/spec/#didcomm-signed-message - Authorisation: establishing whether either party is allowed to request/offer presentations is an application-level concern.
- Validation: apart from verifying the presentation and credentials are signed by a trusted issuer, how credential subject matter fields are checked for disputes is out-of-scope.
Unresolved Questions
- Is a
schema
field needed for thepresentation-offer
andpresentation-request
to identify the types of verifiable credentials and allow forward compatibility for different fields in the message? E.g. aSelectiveDisclosure
or ZKP message may only offer or request certain fields in the credential. Does this relate to thecredentialSchema
field in credentials? - Use
schemas
to negotiate generic form entries as a self-signed credential? E.g. could ask for username, preferred language, comments, any generic information not signed/verified by a third-party issuer from a generic wallet? Similar to Presentation Exchange? https://identity.foundation/presentation-exchange/spec/v1.0.0/ - Identifiers (
id
field) are optional in verifiable credentials. The spec suggests content-addressed identifiers when theid
is not available but their particulars are unclear as there is no spec referenced. This affects thedisputes
reported in thepresentation-result
. - We should RECOMMENDED the
id
of a verifiable credential being a UUID (what version?) in issuance. Needs to be a URI https://www.w3.org/TR/vc-data-model/#identifiers, do UUIDs qualify? e.p.msg.iota.presentation.reject-request.invalid-type
,e.p.msg.iota.presentation.reject-request.invalid-issuer
,e.p.msg.iota.presentation.reject-request.invalid-issuer
ande.p.msg.iota.presentation.reject-request.invalid-type
are specific to CredentialType2021. Should they be listed here? If yes, should they be marked accordingly?
Related Work
- Aries Hyperledger: https://github.com/hyperledger/aries-rfcs/tree/main/features/0454-present-proof-v2
- Jolocom: https://jolocom.github.io/jolocom-sdk/1.0.0/guides/interaction_flows/#credential-verification
- Presentation Exchange: https://identity.foundation/presentation-exchange/spec/v1.0.0/