§ Wallet And Credential Interactions v0.1.0
WACI [wak-ee]
Specification Status: Draft
- Editors:
- Afshan Aman (Bloom)
- Eddie Hedges (Bloom)
- Contributors:
- Jace Hensley (Bloom)
- Participate:
- GitHub repo
- File a bug
- Commit history
§ Abstract
There are interactions between a wallet and relying party that require passing information between the two. WACI provides a standard for these interactions.
§ Status of This Document
WACI is a draft specification under development by Bloom and Affinidi.
§ Interactions
All interactions use the same common blocks:
§ QR Code or Link
Two ways of initiating an interaction is for the relying party to display either a QR code or a link to the user. There could be other ways to initiate an interaction but this document will be discussing QR codes and links.
If the user is using an app/webiste on something other than the device that their wallet is on, then they would be able to scan a QR code with the wallet. But if the user is using the device that also has their wallet then they wouldn’t be able to scan a QR code, they would need to be able to click a link that will open their mobile wallet.
There are of course other use cases where you might need one over the other or both. For example, in an email you may want to display both a link and a QR code because you won’t be able to dynamically choose between the two.
§ Payload
Some mediums do not allow for a large amount of data to be sent (e.g a QR code) to support those cases the initial payload contains instructions for fetching the challenge token.
This is payload can be displayed in a QR code or added to a link as a query parameter.
{
"challengeTokenUrl": "https://example.com/api/get-token/fb28b4ec-4209-4b78-8507-7cc49164cb37",
"version": "1"
}
challengeTokenUrl
:- MUST be unique to the interaction
- MUST be a
GET
endpoint that returns the Token Payload
version
:- This is the version of just the QR/link payload, not the rest of the interaction
§ Token URL Response
The result from GET
ing the provided challengeTokenUrl
. This contains the initial JWT that really starts the interaction.
{
"challengeToken": "{{JWT String}}"
}
§ Challenge Token
// Header
{
"alg": "...",
"kid": "did:example:ebfeb1f712ebc6f1c276e12ec21#primary"
}
- MUST have
alg
andkid
, so the JWT can be verified
// Payload
{
"jti": "...",
"iss": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"aud": "...",
"callbackUrl": "https://example.com/api/callback-url",
"purpose": "...",
"version": "..."
}
- MUST have
iss
- MUST have
jti
to protect against replay attacks - CAN have
aud
if the DID of the wallet is known - MUST have
callbackUrl
- MUST be a
POST
endpoint to take the wallet’s reponse (payload determined by thepurpose
)
- MUST be a
- MUST have
purpose
- MUST have
version
- This is specific to the
purpose
- This is specific to the
§ Callback URL
§ Request
Each interaction will POST
data to the callbackUrl
:
{
"responseToken": "{{Signed JWT}}",
"from": "qr" | "link"
}
responseToken
- A JWT signed by the user, will contain the
challengeToken
- A JWT signed by the user, will contain the
from
- MUST be either “qr” or “link”
- The issuer may need to handle things differently based on how the user is claiming the credentials
§ Response Token
The response token is signed by the user and acts as a way to prove ownership of their DID and to pass aditional data back to the relying party.
{
"alg": "...",
"kid": "did:example:c276e12ec21ebfeb1f712ebc6f1#primary"
}
- MUST have
alg
andkid
, so the JWT can be verified
{
"iss": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"aud": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"challenge": "{{CHALLENGE TOKEN}}"
}
- MUST have
iss
- MUST have
aud
aud
MUST be theiss
of the challenge token
- MUST have
challenge
challenge
MUST be the challenge token given by the issuer
§ Reponse
The POST
to the provided callbackUrl
can return with a simple successful HTTP response or it can return a success with follow up details. A redirectLink
that the app will open in a browser or challengeToken
that will start a new interaction.
{
"redirectUrl": "https://example.com/redirect-url?id={{Some id that identifies the user}}"
}
This could be used to show a success message or bring them back to the website/app to continue where they left off. Most of the time redirectUrl
will only be used when the user is already using their phone (see above).
OR
{
"challengeToken": "{{JWT String}}"
}
This could be used to follow up a request interaction with an offer interaction, or even a chain of request interactions that are based on the previously shared VCs.
§ Token Storage
Because the challenge token is always sent back to the relying party, the token doesn’t need to be stored on creation. And this allows the relying party to not have to worry about someone spamming their API and driving up their storage costs.
But no storage at all can lead to replay attacks. One suggested way to mitigate replay attacks while keeping storage to a minimum is to only store the hash of “used” tokens and have a cron job that cleans this storage based on expiration date of the tokens.
§ Swimlane
Each interaction will be slightly different but will follow this general pattern:
§ Offer/Claim
The offer/claim interaction is for the use case where an issuer wants to give credential(s) to the user.
§ Challenge Token
An example of an offer
challenge token has the following properties (in addition to the base properties):
// Header
{
"alg": "...",
"kid": "did:example:ebfeb1f712ebc6f1c276e12ec21#primary"
}
// Payload
{
"jti": "...",
"iss": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"aud": "...",
"callbackUrl": "https://example.com/api/callback-url",
"purpose": "offer",
"version": "0.1",
"credential_manifest": {
"issuer": {
/* ... */
},
"output_descriptors": [
/* ... */
],
"presentation_definition": {
/* ... */
}
}
}
purpose
MUST be"offer"
- MUST have
credential_manifest
- Uses the Credential Manifest to define the available credentials
- If the
credential_manifest
provides apresentation_definition
the response MUST include averifiable_presentation
§ Callback URL
§ Request
The offer/claim interaction follows the standard Callback URL Request payload, but the responseToken
's is specific to the this interaction.
{
"responseToken": "{{Signed JWT}}",
"from": "qr" | "link"
}
§ Response Token
In addition to the standard responseToken
the offer/claim interaction adds verifiable_presentation
to the payload.
// Header
{
"alg": "...",
"kid": "did:example:c276e12ec21ebfeb1f712ebc6f1#primary"
}
// Payload
{
"iss": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"aud": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"challenge": "{{CHALLENGE TOKEN}}",
"verifiable_presentation": {
/* ... */
"type": ["VerifiablePresentation", "PresentationSubmission"],
"presentation_submission": {
/* ... */
}
/* ... */
}
}
- MUST have
verifiable_presentation
IF the challenge token provides apresentation_definition
- Uses Presentation Exchange’s Presentation Submission
- This
VerifiablePresentation
MUST be aPresentationSubmission
§ Response
In addition to the standard Callback URL Response payload, the offer/claim flow adds verifiable_presentation
:
{
"verifiable_presentation": [
{
/* ... */
"type": ["VerifiablePresentation", "CredentialFulfillment"],
"credential_fulfillment": {
/* ... */
}
/* ... */
}
]
}
OR
{
"verifiable_presentation": [
{
/* ... */
"type": ["VerifiablePresentation", "CredentialFulfillment"],
"credential_fulfillment": {
/* ... */
}
/* ... */
}
]
"redirectUrl": "https://example.com/redirect-url?id={{Some id that identifies the user}}"
}
OR
{
"verifiable_presentation": [
{
/* ... */
"type": ["VerifiablePresentation", "CredentialFulfillment"],
"credential_fulfillment": {
/* ... */
}
/* ... */
}
]
"challengeToken": "{{JWT String}}"
}
verifiable_presentation
MUST be aCredentialFulfillment
presentation- Uses Credential Manifest’s Credential Fulfillment
§ Swimlane
§ Request/Share
The request/share interaction is for the use case where an verifier wants a user to share credential(s) with them.
§ Challenge Token
An example of a request
challenge token has the following properties (in addition to the base properties):
// Header
{
"alg": "...",
"kid": "did:example:ebfeb1f712ebc6f1c276e12ec21#primary"
}
// Payload
{
"jti": "...",
"iss": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"aud": "...",
"callbackUrl": "https://example.com/api/callback-url",
"purpose": "request",
"version": "0.1",
"presentation_definition": {
// ...
}
}
purpose
MUST be"request"
- MUST have
presentation_definition
- Uses Presentation Exchange to define the requirements
§ Callback URL
§ Request
In addition to the standard Callback URL Request payload, the offer/claim flow adds presentation
{
"responseToken": "{{Signed JWT}}",
"from": "qr" | "link"
}
§ Response Token
In addition to the standard responseToken
the offer/claim interaction adds verifiable_presentation
to the payload.
// Header
{
"alg": "...",
"kid": "did:example:c276e12ec21ebfeb1f712ebc6f1#primary"
}
// Paylaod
{
"iss": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"aud": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"challenge": "{{CHALLENGE TOKEN}}",
"verifiable_presentation": {
/* ... */
"type": ["VerifiablePresentation", "PresentationSubmission"],
"presentation_submission": {
/* ... */
}
/* ... */
}
}
- MUST have
verifiable_presentation
- Using Presentation Exchange’s Presentation Submission
- This
VerifiablePresentation
MUST be aPresentationSubmission
- This
VerifiablePresentation
'sproof.challenge
MUST be the challenge token given by the issuer
§ Response
The request/share flow does not add anything to the Callback URL Response.
§ Swimlane
§ Credential Manifest (Working Copy)
Because the Credential Manifest spec is just a strawman at the moment we will rely on a “frozen” copy of the spec outline below. The WACI spec will not be considered stable until the Credential Manifest spec is, but we want to be able to implement early prototypes against something so we need a version of the spec to base it off of.
This is the CM spec as of 02/22/2021.
Alterations in the spec are colored in green
§ Credential Manifest
Specification Status: Strawman
Latest Draft: identity.foundation/credential-manifest
- Editors:
- Daniel Buchner (Microsoft)
- Brent Zundel (Evernym)
- Participate:
- GitHub repo
- File a bug
- Commit history
§ Abstract
For User Agents (e.g. wallets) and other service that wish to engage with Issuers to acquire credentials, there must exist a mechanism for assessing what inputs are required from a Subject to process a request for credential(s) issuance. The Credential Manifest is a common data format for describing the inputs a Subject must provide to an Issuer for subsequent evaluation and issuance of the credential(s) indicated in the Credential Manifest.
Credential Manifests do not themselves define the contents of the output credential(s), the process the Issuer uses to evaluate the submitted inputs, or the protocol Issuers, Subjects, and their User Agents rely on to negotiate credential issuance.
§ Status of This Document
Credential Manifest is a draft specification being developed within the Decentralized Identity Foundation (DIF), and intended for ratification as a DIF recommended data format. This spec will be updated to reflect relevant changes, and participants are encouraged to contribute at the following repository location: https://github.com/decentralized-identity/credential-manifest
§ Terminology
- Decentralized Identifiers
- Unique ID URI string and PKI metadata document format for describing the cryptographic keys and other fundamental PKI values linked to a unique, user-controlled, self-sovereign identifier in a target system (i.e. blockchain, distributed ledger).
- Claim
- An assertion made about a Subject. Used as an umbrella term for Credential, Assertion, Attestation, etc.
- Issuer
- Issuers are entities that issue credentials to a Holder.
- Holder
- Holders are entities that recieve credentials from Issuers, possibly first submitting proofs the the Issuer to satisfy the requirements described in a Presentation Definition.
- Output Descriptor
- Output Descriptors are used by an Issuer to describe the credentials they are offering to a Holder. See Output Descriptor
- Output Descriptor Object
- Output Descriptor Objects are populated with properties describing the Claims the Issuer is offering the Holder
- Credential Fulfillment
- Credential Fulfillments are objects embedded within target claim negotiation formats that unify the presentation of Claims to a Holder in accordance with the output an Issuer specified in a Credential Manifest. See Credential Fulfillment.
§ Resource Definition
Credential Manifests are a resource format that defines preconditional requirements, Issuer style preferences, and other facets User Agents utilize to help articulate and select the inputs necessary for processing and issuance of a specified credential.
{
"id": "WA-DL-CLASS-A",
"version": "0.1.0",
"issuer": {
"id": "did:example:123?linked-domains=3",
"name": "Washington State Government",
"styles": {
"thumbnail": {
"uri": "https://dol.wa.com/logo.png",
"alt": "Washington State Seal"
},
"hero": {
"uri": "https://dol.wa.com/people-working.png",
"alt": "People working on serious things"
},
"background": {
"color": "#ff0000"
},
"text": {
"color": "#d4d400"
}
}
},
"output_descriptors": [
{
"schema": [{
"uri": "http://washington-state-schemas.org/1.0.0/driver-license.json"
}],
"display": {
"title": {
"path": ["$.name", "$.vc.name"],
"text": "Washington State Driver License"
},
"subtitle": {
"path": ["$.class", "$.vc.class"],
"text": "Class A, Commercial"
},
"description": {
"text": "License to operate a vehicle with a gross combined weight rating (GCWR) of 26,001 or more pounds, as long as the GVWR of the vehicle(s) being towed is over 10,000 pounds."
},
"properties": [
{
"path": ["$.donor", "$.vc.donor"],
"label": "Organ Donor"
}
]
},
"styles": {
"thumbnail": {
"uri": "https://dol.wa.com/logo.png",
"alt": "Washington State Seal"
},
"hero": {
"uri": "https://dol.wa.com/happy-people-driving.png",
"alt": "Happy people driving"
},
"background": {
"color": "#ff0000"
},
"text": {
"color": "#d4d400"
}
}
}
],
"presentation_definition": {
// As defined in the Presentation Exchange specification
}
}
§ General Composition
Credential Manifests are JSON objects composed as follows:
- The object MUST contain an
issuer
property, and its value MUST be an object composed as follows:- The object must contain a
id
property, and its value must be a valid URI string that identifies who the issuer of the credential(s) will be. - The object MAY contain a
name
property, and its value must be a string that SHOULD reflect the human-readable name the Issuer wishes to be recognized by. - The object MAY contain a
styles
property, and its value must be an object composed as defined in thestyles
properties section.
- The object must contain a
- The object MUST contain an
output_descriptors
property. It’s vault MUST be an array of Output Descriptor Objects, the composition of which are described in theOutput Descriptor
section below - The object MAY contain a
presentation_definition
object, and its value MUST be a Presentation Definition object, as defined by the DIF Presentation Exchange specification.
§ Output Descriptor
Output Descriptors are objects used to describe the Claims a Issuer if offering to a Holder.
Output Descriptor Objects contain schema URI that links to the schema of the offered output data, and information about how to display the output to the Holder.
{
"output_descriptors": [
{
"id": "driver_license_output",
"schema": "https://schema.org/EducationalOccupationalCredential",
"display": {
"title": {
"path": ["$.name", "$.vc.name"],
"text": "Washington State Driver License"
},
"subtitle": {
"path": ["$.class", "$.vc.class"],
"text": "Class A, Commercial"
},
"description": {
"text": "License to operate a vehicle with a gross combined weight rating (GCWR) of 26,001 or more pounds, as long as the GVWR of the vehicle(s) being towed is over 10,000 pounds."
},
"properties": [
{
"path": ["$.donor", "$.vc.donor"],
"label": "Organ Donor"
}
]
},
"styles": {
"thumbnail": {
"uri": "https://dol.wa.com/logo.png",
"alt": "Washington State Seal"
},
"hero": {
"uri": "https://dol.wa.com/happy-people-driving.png",
"alt": "Happy people driving"
},
"background": {
"color": "#ff0000"
},
"text": {
"color": "#d4d400"
}
}
}
]
}
§ Output Descriptor Object
Output Descriptor Objects are composed as follows:
- The Output Descriptor Object MUST contain an
id
property. The value of theid
property MUST be a string that does not conflict with theid
of another Output Descriptor Object in the same Credential Manifest. - The Output Descriptor Object MUST contain a
schema
property, and its value MUST be an array composed of schema objects for the schema(s) of the credentials to be issued. - The Output Descriptor Object MAY contain a
name
property, and if present its value SHOULD be a human-friendly name that describes what the credential represents. - The Output Descriptor Object MAY contain a
description
property, and if present its value MUST be a string that describes what the credential is in greater detail. - The Output Descriptor Object MAY contain a
styles
property, and its value must be an object composed as defined in thestyles
properties section. - The Output Descriptor Object MAY contain a
display
property, and its value must be an object composed as defined in thedisplay
properties section.
§ styles
properties
Within a Credential Manifest
, there are two areas where styling affordances are provided: under the issuer
property, where the Issuer expresses information about themselves - including how a User Agent should style UI that represents the Issuer, and under the credential
property, where the Issuer expresses information about the credntial itself - including how a User Agent should style UI for the credential itself. Under each of these areas an implementer MAY include a styles
property, and if present, its value must be an object composed of the following properties:
- The object MAY contain a
thumbnail
property, and if present, its value MUST be an object with the following optional properties:- The object MUST contain a
uri
property, and if present its value MUST be a valid URI string to an image resource. - The object MAY contain an
alt
property, and if present its value MUST be a string that describes the alternate text for the logo image.
- The object MUST contain a
- The object MAY contain a
hero
property, and if present, its value MUST be an object with the following optional properties:- The object MUST contain a
uri
property, and if present its value MUST be a valid URI string to an image resource. - The object MAY contain an
alt
property, and if present its value MUST be a string that describes the alternate text for the logo image.
- The object MUST contain a
- The object MAY contain a
background
property, and if present, its value MUST be an object with the following optional properties:- The object MAY contain a
color
property, and if present its value MUST be a HEX string color value (e.g. #000000).
- The object MAY contain a
- The object MAY contain a
text
property, and if present, its value MUST be an object with the following optional properties:- The object MAY contain a
color
property, and if present its value MUST be a HEX string color value (e.g. #000000).
- The object MAY contain a
§ display
properties
The credential
property of a Credential Manifest
is an object that MAY contain a display
property defining various content and data pointers for representation of a credential in UI. The properties in the object use Display Mapping Objects to assign text and data about the credential to common UI presentation elements, either by selecting data from the credential itself or providing it directly. The display
object is constructed as follows
- The object MAY contain a
title
property, and if present, its value MUST be a Display Mapping Object. User Agents SHOULD render the data in an area of UI that conveys the general title of the credential being rendered. - The object MAY contain a
subtitle
property, and if present, its value MUST be a Display Mapping Object. User Agents SHOULD render the data in close proximity to thetitle
value and SHOULD display the information in a way that is noticably less pronounced than that of thetitle
value. - The object MAY contain a
description
property, and if present, its value MUST be a Display Mapping Object. User Agents SHOULD render the data in an area of UI that is appropreate for verbose, descriptive textual data. - The object MAY contain a
properties
property, and if present, its value MUST be an array of Display Mapping Objects. User Agents SHOULD render the data specified by each Display Mapping Object in an area of UI that is appropreate for the rendering of a flat list of labeled values.
§ Display Mapping Objects
{
"display": {
"title": {
"path": ["$.name", "$.vc.name"],
"text": "Washington State Driver License"
},
"properties": [
{
"path": ["$.vision_aid", "$.vc.vision_aid"],
"label": "Vision aid required"
},
{
"path": ["$.donor", "$.vc.donor"],
"label": "Organ Donor"
}
]
}
}
The Display Mapping Objects are JSON objects constructed as follows:
- The object MAY contain a
path
property, and if present, its value MUST be a JSONPath string expression and the result MUST be a string or numeric value that is rendered in the UI - The object MAY contain a
text
property, and if present, its value MUST be a string or numeric value that is rendered in the UI if nopath
property is specified within the object, or all of thepath
property’s array of JSONPath string expressions fail to select data within the target credential. - The object MAY contain a
label
property, and if present, its value MUST be a string that is rendered in the UI where a labled display of thepath
ortext
value is appropreate. If the property is intended for labeled display, the label SHOULD be shown in the UI and the value paired with the label SHOULD be either data selected from the processing of thepath
property’s JSONPath string expressions, or the value specified by thetext
property. If neither is present, display of the label and any fallback value is at the election of the implementer.
§ Resource Location
Credential Manifests should be retrievable at known, semantic locations that are generalized across all entities, protocols, and transports. This specification does not stipulate how Credential Manifests must be located, hosted, or retrieved, but does advise that Issuers SHOULD make their Credential Manifests available via an instance of the forthcoming semantic personal datastore standard being developed by DIF, W3C, and other groups (e.g. Identity Hubs).
§ Credential Fulfillment
Credential Fulfillments are objects embedded within target
Claim negotiation formats that express how the outputs presented as
proofs to a Holder are provided in accordance with the outpus
specified in a Credential Manifest. Embedded
Credential Fulfillment objects MUST be located within target
data format as the value of a credential_fulfillment
property, which is
composed and embedded as follows:
- The
credential_fulfillment
object MUST be included at the top-level of an Embed Target, or in the specific location described in the Embed Locations table in the Embed Target section below. - The
credential_fulfillment
object MUST contain anid
property. The value of this property MUST be a unique identifier, such as a UUID. - The
credential_fulfillment
object MUST contain amanifest_id
property. The value of this property MUST be theid
value of a valid Credential Manifest. - The
credential_fulfillment
object MUST include adescriptor_map
property. The value of this property MUST be an array of Output Descriptor Mapping Objects, composed as follows:- The
descriptor_map
object MUST include anid
property. The value of this property MUST be a string that matches theid
property of the Output Descriptor in the Credential Manifest that this Credential Fulfillment is related to. - The
descriptor_map
object MUST include aformat
property. The value of this property MUST be a string that matches one of the Claim Format Designation. This denotes the data format of the Claim. - The
descriptor_map
object MUST include apath
property. The value of this property MUST be a JSONPath string expression. Thepath
property indicates the Claim submitted in relation to the identified Output Descriptor, when executed against the top-level of the object the Credential Fulfillment is embedded within. - The object MAY include a
path_nested
object to indicate the presence of a multi-Claim envelope format. This means the Claim indicated is to be decoded separately from its parent enclosure.- The format of a
path_nested
object mirrors that of adescriptor_map
property. The nesting may be any number of levels deep. Theid
property MUST be the same for each level of nesting. - The
path
property inside eachpath_nested
property provides a relative path within a given nested value.
- The format of a
- The
{
// NOTE: VP, OIDC, DIDComm, or CHAPI outer wrapper properties would be here
"credential_fulfillment": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"manifest_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"descriptor_map": [
{
"id": "banking_output_2",
"format": "jwt_vc",
"path": "$.verifiableCredential[0]"
},
{
"id": "employment_output",
"format": "ldp_vc",
"path": "$.verifiableCredential[1]"
},
{
"id": "citizenship_output_1",
"format": "ldp_vc",
"path": "$.verifiableCredential[2]"
}
]
}
}
§ Processing of path_nested
Entries
{
"credential_fulfillment": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"manifest_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"descriptor_map": [
{
"id": "banking_output_2",
"format": "jwt_vp",
"path": "$.outerClaim[0]",
"path_nested": {
"id": "banking_output_2",
"format": "ldp_vc",
"path": "$.innerClaim[1]",
"path_nested": {
"id": "banking_output_2",
"format": "jwt_vc",
"path": "$.mostInnerClaim[2]"
}
}
}
]
}
}
When the path_nested
property is present in a Credential Fulfillment
object, process as follows:
- For each Nested Submission Traversal Object in the
path_nested
array:- Execute the JSONPath expression string on the Current Traversal Object, or if none is designated, the top level of the Embed Target.
- Decode and parse the value returned from
JSONPath execution in
accordance with the Claim Format Designation
specified in the object’s
format
property. If the value parses and validates in accordance with the Claim Format Designation specified, let the resulting object be the Current Traversal Object - If present, process the next Nested Submission Traversal Object in the
current
path_nested
property.
- If parsing of the Nested Submission Traversal Objects in the
path_nested
property produced a valid value, process it as the submission against the Output Descriptor indicated by theid
property of the containing Output Descriptor Mapping Object.
§ Embed Targets
The following section details where the Credential Fulfillment is to be embedded within a target data structure, as well as how to formulate the JSONPath expressions to select the Claims within the target data structure.
§ Embed Locations
The following are the locations at which the credential_manifest
object
MUST be embedded for known target formats. For any location besides
the top level of the embed target, the location is described in JSONPath syntax.
Target | Location |
---|---|
VP | top-level |
§ JSON Schema
The following JSON Schema Draft 7 definition summarizes the rules above:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Credential Fulfillment",
"type": "object",
"properties": {
"credential_fulfillment": {
"type": "object",
"properties": {
"id": { "type": "string" },
"manifest_id": { "type": "string" },
"descriptor_map": {
"type": "array",
"items": { "$ref": "#/definitions/descriptor" }
}
},
"required": ["id", "manifest_id", "descriptor_map"],
"additionalProperties": false
}
},
"definitions": {
"descriptor": {
"type": "object",
"properties": {
"id": { "type": "string" },
"path": { "type": "string" },
"path_nested": {
"type": "object",
"$ref": "#/definitions/descriptor"
},
"format": {
"type": "string",
"enum": ["jwt", "jwt_vc", "jwt_vp", "ldp", "ldp_vc", "ldp_vp"]
}
},
"required": ["id", "path", "format"],
"additionalProperties": false
}
},
"required": ["credential_fulfillment"],
"additionalProperties": false
}
§ Appendix
§ Embed Target Examples
§ Credential Fulfillment
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/credential-manifest/fulfillment/v1"
],
"type": [
"VerifiablePresentation",
"CredentialFulfillment"
],
"credential_fulfillment": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"manifest_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"descriptor_map": [
{
"id": "banking_output_2",
"format": "jwt_vc",
"path": "$.verifiableCredential[0]"
},
{
"id": "employment_output",
"format": "ldp_vc",
"path": "$.verifiableCredential[1]"
},
{
"id": "citizenship_output_1",
"format": "ldp_vc",
"path": "$.verifiableCredential[2]"
}
]
},
"verifiableCredential": [
{
"comment": "IN REALWORLD VPs, THIS WILL BE A BIG UGLY OBJECT INSTEAD OF THE DECODED JWT PAYLOAD THAT FOLLOWS",
"vc": {
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "https://eu.com/claims/DriversLicense",
"type": ["EUDriversLicense"],
"issuer": "did:example:123",
"issuanceDate": "2010-01-01T19:73:24Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"accounts": [
{
"id": "1234567890",
"route": "DE-9876543210"
},
{
"id": "2457913570",
"route": "DE-0753197542"
}
]
}
}
},
{
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "https://business-standards.org/schemas/employment-history.json",
"type": ["VerifiableCredential", "GenericEmploymentCredential"],
"issuer": "did:foo:123",
"issuanceDate": "2010-01-01T19:73:24Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"active": true
},
"proof": {
"type": "EcdsaSecp256k1VerificationKey2019",
"created": "2017-06-18T21:19:10Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "https://example.edu/issuers/keys/1",
"jws": "..."
}
},
{
"@context": "https://www.w3.org/2018/credentials/v1",
"id": "https://eu.com/claims/DriversLicense",
"type": ["EUDriversLicense"],
"issuer": "did:foo:123",
"issuanceDate": "2010-01-01T19:73:24Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"license": {
"number": "34DGE352",
"dob": "07/13/80"
}
},
"proof": {
"type": "RsaSignature2018",
"created": "2017-06-18T21:19:10Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "https://example.edu/issuers/keys/1",
"jws": "..."
}
}
],
"proof": {
"type": "RsaSignature2018",
"created": "2018-09-14T21:19:10Z",
"proofPurpose": "authentication",
"verificationMethod": "did:example:ebfeb1f712ebc6f1c276e12ec21#keys-1",
"challenge": "1f44d55f-f161-4938-a659-f8026467f126",
"domain": "4jt78h47fh47",
"jws": "..."
}
}