§ Presentation Exchange
Specification Status: Working Group Draft
Latest Draft: identity.foundation/presentation-exchange
- Editors:
- Daniel Buchner (Microsoft)
- Brent Zundel (Evernym)
- Martin Riedel (Civic Technologies)
- Contributors:
- Gabe Cohen (Workday)
- Orie Steele (Transmute)
- Wayne Chang (Spruce)
- Participate:
- GitHub repo
- File a bug
- Commit history
§ Abstract
A common activity between peers in identity systems that feature the ability to generate self-asserted and third-party issued claims is the demand and submission of proofs from a Holder to a Verifier. This flow implicitly requires the Holder and Verifier have a known mechanism to facilitate the two primary steps in a proving exchange: the way Verifiers define the proof requirements, and how Holders must encode submissions of proof to align with those requirements.
To address these needs, this Presentation Exchange specification codifies the
Presentation Definition
data format Verifiers can use to articulate proof
requirements, as well as the Presentation Submission
data format Holders can
use to submit proofs in accordance with them. The specification is designed to
be both claim format and transport envelope agnostic, meaning an implementer
can use JSON Web Tokens (JWTs),
Verifiable Credentials (VCs),
JWT-VCs,
or any other claim format, and convey them
via Open ID Connect, DIDComm,
Credential Handler API,
or any other transport envelope. The goal of
this flexible format and transport agnostic mechanism is to nullify the
redundant handling, code, and hassle involved in presenting and satisfying
logical requirements across formats and transport envelopes.
This specification does not endeavor to define transport protocols, specific endpoints, or other means for conveying the formatted objects it codifies, but encourages other specifications and projects that do define such mechanisms to utilize these data formats within their flows.
§ Status of This Document
Presentation Exchange is a draft specification under development within the Decentralized Identity Foundation (DIF), and designed to incorporate the requirements and learnings from related work of the most active industry players into a shared specification that meets the collective needs of the community. This spec is regularly updated to reflect relevant changes, and we encourage active engagement on GitHub (see above) and other mediums (e.g. DIF) where this work is being done.
§ 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).
- Holder
- The entity that submits proofs to a Verifier to satisfy the requirements described in a Presentation Definition
- Verifier
- The entity that defines what proofs they require from a Holder (via a Presentation Definition) in order to proceed with an interaction.
- Claim
- An assertion made about a given entity. Used as an umbrella term for Credential, Assertion, Attestation, etc.
- Presentation Definition
- Presentation Definitions are objects that articulate what proofs a Verifier requires. These help the Verifier to decide how or whether to interact with a Holder. Presentation Definitions are composed of inputs, which describe the forms and details of the proofs they require, and optional sets of selection rules, to allow Holders flexibility in cases where many different types of proofs may satisfy an input requirement.
- Presentation Request
- Presentation Requests are transport mechanisms for Presentation Definitions. Presentation Requests can take multiple shapes, using a variety of protocols and signature schemes not defined in this specification. They are sent by a Verifier to a Holder.
- Presentation Submission
- Presentation Submissions are objects embedded within target claim negotiation formats that unify the presentation of proofs to a Verifier in accordance with the requirements a Verifier specified in a Presentation Definition.
- Input Descriptor
- Input Descriptors are objects used to describe the information a Verifier requires of a Holder before they will proceed with an interaction.
- Submission Requirement
- Submission Requirements are objects that define what combinations of inputs must be submitted to comply with the requirements a Verifier has for proceeding in a flow (e.g. credential issuance, allowing entry, accepting an application).
§ Localization
To support localization, IETF BCP 47 one
MAY use language tags under the locale
property in both a Presentation Definition
and Presentation Submission
. If a Definition has a language tag,
so should the corresponding Submission. A Submission may have a language tag
regardless of the presence of one in the corresponding Definition.
Wrapping transports such as HTTP may choose to utlilize the locale
property in
conjunction with the
Accept-Language header.
{
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"locale": "en-US",
"input_descriptors": [{
"id": "name_input",
"name": "Full Legal Name",
"purpose": "We need your full legal name.",
"schema": [
{
"uri": "https://name-standards.com/name.json",
"required": true
}
]
}]
}
}
{
"presentation_submission": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"definition_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"locale": "de-DE",
"descriptor_map": [{
"id": "name_input",
"path": "$.verifiableCredential[0]"
}]
}
}
§ Presentation Definition
Presentation Definitions are objects that articulate what proofs a Verifier requires. These help the Verifier to decide how or whether to interact with a Holder. Presentation Definitions are composed of inputs, which describe the forms and details of the proofs they require, and optional sets of selection rules, to allow Holders flexibility in cases where many different types of proofs may satisfy an input requirement.
{
// VP, OIDC, DIDComm, or CHAPI outer wrapper
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"input_descriptors": [
{
"id": "banking_input",
"name": "Bank Account Information",
"purpose": "We need your bank and account information.",
"schema": [
{
"uri": "https://bank-standards.com/customer.json"
}
],
"constraints": {
"limit_disclosure": true,
"fields": [
{
"path": ["$.issuer", "$.vc.issuer", "$.iss"],
"purpose": "The claim must be from one of the specified issuers",
"filter": {
"type": "string",
"pattern": "did:example:123|did:example:456"
}
}
]
}
},
{
"id": "citizenship_input",
"name": "US Passport",
"schema": [
{
"uri": "hub://did:foo:123/Collections/schema.us.gov/passport.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.credentialSubject.birth_date", "$.vc.credentialSubject.birth_date", "$.birth_date"],
"filter": {
"type": "string",
"format": "date",
"minimum": "1999-5-16"
}
}
]
}
}
]
}
}
{
// VP, OIDC, DIDComm, or CHAPI outer wrapper
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"submission_requirements": [{
"name": "Citizenship Information",
"rule": "pick",
"count": 1,
"from": "A"
}],
"input_descriptors": [
{
"id": "citizenship_input_1",
"name": "EU Driver's License",
"group": ["A"],
"schema": [
{
"uri": "https://eu.com/claims/DriversLicense.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.issuer", "$.vc.issuer", "$.iss"],
"purpose": "The claim must be from one of the specified issuers",
"filter": {
"type": "string",
"pattern": "did:example:gov1|did:example:gov2"
}
},
{
"path": ["$.credentialSubject.dob", "$.vc.credentialSubject.dob", "$.dob"],
"filter": {
"type": "string",
"format": "date",
"maximum": "1999-6-15"
}
}
]
}
},
{
"id": "citizenship_input_2",
"name": "US Passport",
"group": ["A"],
"schema": [
{
"uri": "hub://did:foo:123/Collections/schema.us.gov/passport.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.credentialSubject.birth_date", "$.vc.credentialSubject.birth_date", "$.birth_date"],
"filter": {
"type": "string",
"format": "date",
"maximum": "1999-5-16"
}
}
]
}
}
]
}
}
{
// VP, OIDC, DIDComm, or CHAPI outer wrapper
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"submission_requirements": [
{
"name": "Banking Information",
"purpose": "We need to know if you have an established banking history.",
"rule": "pick",
"count": 1,
"from": "A"
},
{
"name": "Employment Information",
"purpose": "We need to know that you are currently employed.",
"rule": "all",
"from": "B"
},
{
"name": "Citizenship Information",
"rule": "pick",
"count": 1,
"from": "C"
}
],
"input_descriptors": [
{
"id": "banking_input_1",
"name": "Bank Account Information",
"purpose": "We need your bank and account information.",
"group": ["A"],
"schema": [
{
"uri": "https://bank-standards.com/customer.json"
}
],
"constraints": {
"limit_disclosure": true,
"fields": [
{
"path": ["$.issuer", "$.vc.issuer", "$.iss"],
"purpose": "The claim must be from one of the specified issuers",
"filter": {
"type": "string",
"pattern": "did:example:123|did:example:456"
}
},
{
"path": ["$.credentialSubject.account[*].account_number", "$.vc.credentialSubject.account[*].account_number", "$.account[*].account_number"],
"purpose": "We need your bank account number for processing purposes",
"filter": {
"type": "string",
"minLength": 10,
"maxLength": 12
}
},
{
"path": ["$.credentialSubject.account[*].routing_number", "$.vc.credentialSubject.account[*].routing_number", "$.account[*].routing_number"],
"purpose": "You must have an account with a German, US, or Japanese bank account",
"filter": {
"type": "string",
"pattern": "^DE|^US|^JP"
}
}
]
}
},
{
"id": "banking_input_2",
"name": "Bank Account Information",
"purpose": "We need your bank and account information.",
"group": ["A"],
"schema": [
{
"uri": "https://bank-schemas.org/1.0.0/accounts.json"
},
{
"uri": "https://bank-schemas.org/2.0.0/accounts.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.issuer", "$.vc.issuer", "$.iss"],
"purpose": "The claim must be from one of the specified issuers",
"filter": {
"type": "string",
"pattern": "did:example:123|did:example:456"
}
},
{
"path": ["$.credentialSubject.account[*].id", "$.vc.credentialSubject.account[*].id", "$.account[*].id"],
"purpose": "We need your bank account number for processing purposes",
"filter": {
"type": "string",
"minLength": 10,
"maxLength": 12
}
},
{
"path": ["$.credentialSubject.account[*].route", "$.vc.credentialSubject.account[*].route", "$.account[*].route"],
"purpose": "You must have an account with a German, US, or Japanese bank account",
"filter": {
"type": "string",
"pattern": "^DE|^US|^JP"
}
}
]
}
},
{
"id": "employment_input",
"name": "Employment History",
"purpose": "We need to know your work history.",
"group": ["B"],
"schema": [
{
"uri": "https://business-standards.org/schemas/employment-history.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.jobs[*].active"],
"filter": {
"type": "boolean",
"pattern": "true"
}
}
]
}
},
{
"id": "citizenship_input_1",
"name": "EU Driver's License",
"group": ["C"],
"schema": [
{
"uri": "https://eu.com/claims/DriversLicense.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.issuer", "$.vc.issuer", "$.iss"],
"purpose": "The claim must be from one of the specified issuers",
"filter": {
"type": "string",
"pattern": "did:example:gov1|did:example:gov2"
}
},
{
"path": ["$.credentialSubject.dob", "$.vc.credentialSubject.dob", "$.dob"],
"filter": {
"type": "string",
"format": "date",
"minimum": "1999-5-16"
}
}
]
}
},
{
"id": "citizenship_input_2",
"name": "US Passport",
"group": ["C"],
"schema": [
{
"uri": "hub://did:foo:123/Collections/schema.us.gov/passport.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.credentialSubject.birth_date", "$.vc.credentialSubject.birth_date", "$.birth_date"],
"filter": {
"type": "string",
"format": "date",
"minimum": "1999-5-16"
}
}
]
}
}
]
}
}
The following properties are for use at the top-level of the resource — all other properties that are not defined below MUST be ignored:
id
- The resource MUST contain this property uniquely identifying the resource. The property MUST be a unique identifier, such as a UUID.name
- The resource MAY contain this property, and if present its value SHOULD be a human-friendly name that describes what the Presentation Definition pertains to.purpose
- The resource MAY contain this property, and if present its value MUST be a string that describes the purpose for which the Presentation Definition’s inputs are being requested.- The resource MAY include a
format
property, and its value MUST be an object with one or more properties matching the registered Claim Format Designations (jwt
,jwt_vc
,jwt_vp
, etc.) to inform the Holder of the claim format configurations the Verifier can process. The value for each property included MUST be an object composed as follows:-
The object MUST include a format-specific property (i.e.
alg
,proof_type
) that expresses which algorithms the Verifier supports for the format, and if present, its value MUST be an array of one or more of the format-specific algorithmic identifier references, as noted in the Claim Format Designations section.{ "presentation_definition": { "format": { "jwt": { "alg": ["EdDSA", "ES256K", "ES384"] }, "jwt_vc": { "alg": ["ES256K", "ES384"] }, "jwt_vp": { "alg": ["EdDSA", "ES256K"] }, "ldp_vc": { "proof_type": [ "JsonWebSignature2020", "Ed25519Signature2018", "EcdsaSecp256k1Signature2019", "RsaSignature2018" ] }, "ldp_vp": { "proof_type": ["Ed25519Signature2018"] }, "ldp": { "proof_type": ["RsaSignature2018"] } } } }
-
submission_requirements
- The resource MAY contain this property, and if present, its value MUST conform to the Submission Requirement Format. If not present, all inputs listed in theinput_descriptors
array are required for submission. The description for the format of this property is in theSubmission Requirement
section below.input_descriptors
- The resource MUST contain this property, and its value MUST be an array of Input Descriptor objects. If nosubmission_requirements
is present, all inputs listed in theinput_descriptors
array are required for submission. The composition of values under this property are described in theInput Descriptors
section below.
§ Submission Requirements
Presentation Definitions MAY include Submission Requirements,
which are objects that define what combinations of inputs must be submitted
to comply with the requirements a Verifier has for proceeding in a flow (e.g.
claim issuance, allowing entry, accepting an application).
Submission Requirements introduce a set of rule types and mapping instructions
a User Agent can ingest to present requirement optionality to the user, and
subsequently submit inputs in a way that maps back to the rules the verifying
party has asserted (via a Proof Submission
object). The following section
defines the format for Submission Requirement objects, and the selection syntax
verifying parties can use to specify which combinations of inputs are acceptable.
If present, all members of the submission_requirements
array MUST
be satisfied, and all input_descriptors MUST be grouped. Any unused
input_descriptors that remain after satisfying all submission_requirements
MUST be ignored.
"submission_requirements": [
{
"name": "Banking Information",
"purpose": "We need to know if you have an established banking history.",
"rule": "pick",
"count": 1,
"from": "A"
},
{
"name": "Employment Information",
"purpose": "We need to know that you are currently employed.",
"rule": "all",
"from": "B"
},
{
"name": "Citizenship Information",
"rule": "pick",
"count": 1,
"from_nested": [
{
"name": "United States Citizenship Proofs",
"purpose": "We need you to prove you are a US citizen.",
"rule": "all",
"from": "C"
},
{
"name": "European Union Citizenship Proofs",
"purpose": "We need you to prove you are a citizen of a EU country.",
"rule": "all",
"from": "D"
}
]
}
]
§ Submission Requirement Objects
Submission Requirement Objects describe combinations of inputs that must be submitted via a Presentation Submission to satisfy Verifier demands. Submission Requirement Objects are JSON objects constructed as follows:
- The object MUST contain a
rule
property, and its value MUST be a string matching one of the Submission Requirement Rules values listed in the section below. - The object MUST contain either a
from
orfrom_nested
property. If both properties are present, the implementation MUST produce an error. The values of thefrom
andfrom_nested
properties are defined as follows:from
- the value of thefrom
property must be agroup
string matching one of thegroup
strings specified for one or more Input Descriptor objects.from_nested
- an array of nested Submission Requirement Objects.
- The object MAY contain a
name
property, and if present, its value MUST be a string which MAY be used by a consuming User Agent to display the general name of the requirement set to a user. - The object MAY contain a
purpose
property and, if present, its value MUST be a string that describes the purpose for which the specified requirement is being asserted. - The object MAY contain additional properties as required by
Submission Requirement Rules, such as
count
,min
, andmax
for the"pick"
rule.
§ Submission Requirement Rules
Submission Requirement Rules
{id=“requirement-rules”} are used within Submission Requirement Objects to
describe the specific combinatorial rule that must be applied to submit a
particular subset of required inputs. Rules are selected by populating the
rule
property with the corresponding string. An implementation MUST
support the following standard types:
§ all
rule
- The object must contain a
rule
property, and its value MUST be the string"all"
. - The object MUST contain either a
from
orfrom_nested
property, which behave as follows when used in anall
rule:from
- when used within anall
rule, every Input Descriptor matching the group string of thefrom
value must be submitted to the Verifier.from_nested
- when used within anall
rule, all the Submission Requirement Objects specified in thefrom_nested
array must be satisfied by the inputs submitted in a subsequent Presentation Submission.
"submission_requirements": [
{
"name": "Submission of educational transcripts",
"purpose": "We need all your educational transcripts to process your application",
"rule": "all",
"from": "A"
}
]
§ pick
rule
- The Submission Requirement object’s
rule
property MUST contain the string value"pick"
. - The Submission Requirement object MAY contain a
count
property, and if present, its value MUST be an integer greater than zero. - The Submission Requirement object MAY contain a
min
property, and if present, its value MUST be an integer greater than or equal to zero. - The Submission Requirement object MAY contain a
max
property, and if present, its value MUST be an integer greater than zero, and, if also present, greater than the value of themin
property. - The Submission Requirement object MUST contain either a
from
property or afrom_nested
property, and of whichever are present, all inputs from thefrom
group string specified or Submission Requirements in thefrom_nested
array MUST be submitted or satisfied.
If the from
property contains a group
string, it directs the consumer of
the Presentation Definition to submit all members of the matching group
string. In the following example, the from
property contains a group
string to require a single member of group "B"
:
"submission_requirements": [
{
"name": "Citizenship Proof",
"purpose": "We need to confirm you are a citizen of one of the following countries",
"rule": "pick",
"count": 1,
"from": "B"
}
]
"submission_requirements": [
{
"name": "Citizenship Proof",
"purpose": "We need to confirm you are a citizen of one of the following countries",
"rule": "pick",
"min": 2,
"max": 4,
"from": "B"
}
]
If the from
property contains an array of nested Submission Requirement
objects, it directs the consumer of the Presentation Definition to submit
members such that the number of satisfied Submission Requirement objects is
exactly count
. In the following example, the from
property contains an
array of nested Submission Requirement objects to require either all members
from group "A"
or two members from group "B"
:
"submission_requirements": [
{
"name": "Confirm banking relationship or employment and residence proofs",
"purpose": "Submit your bank statement or proofs of employment and residence to process your loan",
"rule": "pick",
"count": 1,
"from_nested": [
{ "rule": "all", "from": "A" },
{ "rule": "pick", "count": 2, "from": "B" }
]
}
]
§ JSON Schema
The following JSON Schema Draft 7 definition summarizes many of the format-related rules above:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"submission_requirements": {
"type": "object",
"oneOf": [
{
"properties": {
"name": { "type": "string" },
"purpose": { "type": "string" },
"rule": {
"type": "string",
"enum": ["all", "pick"]
},
"count": { "type": "integer", "minimum": 1 },
"from": { "type": "string" }
},
"required": ["rule", "from"],
"additionalProperties": false
},
{
"properties": {
"name": { "type": "string" },
"purpose": { "type": "string" },
"rule": {
"type": "string",
"enum": ["all", "pick"]
},
"count": { "type": "integer", "minimum": 1 },
"from_nested": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/submission_requirements"
}
}
},
"required": ["rule", "from_nested"],
"additionalProperties": false
}
]
}
},
"type": "object",
"properties": {
"submission_requirements": {
"type": "array",
"items": {
"$ref": "#/definitions/submission_requirements"
}
}
},
"required": ["submission_requirements"],
"additionalProperties": false
}
§ Property Values and Evaluation
The following property value and evaluation guidelines summarize many of the processing-related rules above:
- The
rule
property value may be either"all"
or"pick"
, and the implementation MUST produce an error if an unknownrule
value is present. - The Submission Requirement MUST contain a
from
property or afrom_nested
property, not both, and if present their values must be a string or an array, respectively. If any of these conditions are not met, the implementation MUST produce an error. - To determine whether a Submission Requirement is satisfied, used the
following algorithm:
- If the
rule
is"all"
, then the Submission Requirement MUST contain afrom
property or afrom_nested
property, and of whichever are present, all inputs from thefrom
group string specified or Submission Requirements in thefrom_nested
array MUST be submitted or satisfied, respectively. - If the
rule
is"pick"
, then the Submission Requirement MUST contain afrom
property or afrom_nested
property, and of whichever are present, they must be evaluated as follows:- if a
count
property is present, the number of inputs submitted, or nested Submission Requirements satisfied, MUST be exactly equal to the value ofcount
property. - if a
min
property is present, the number of inputs submitted, or nested Submission Requirements satisfied, MUST be equal to or greater than the value of themin
property. - if a
max
property is present, the number of inputs submitted, or nested Submission Requirements satisfied, MUST be equal to or less than the value of themax
property.
- if a
- If the
§ Input Descriptors
Input Descriptors are objects used to describe the information a Verifier
requires of a Holder before they will proceed with an interaction. If no
submission_requirements
objects are present, all input_descriptor
objects
MUST be satisfied.
Input Descriptor Objects contain a schema URI that links to the schema of the required input data, constraints on data values, and an explanation why a certain item or set of data is being requested:
"input_descriptors": [
{
"id": "banking_input_1",
"name": "Bank Account Information",
"purpose": "We need your bank and account information.",
"group": ["A"],
"schema": [
{
"uri": "https://bank-schemas.org/1.0.0/accounts.json"
},
{
"uri": "https://bank-schemas.org/2.0.0/accounts.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.issuer", "$.vc.issuer", "$.iss"],
"purpose": "The claim must be from one of the specified issuers",
"filter": {
"type": "string",
"pattern": "did:example:123|did:example:456"
}
},
{
"path": ["$.credentialSubject.account[*].id", "$.vc.credentialSubject.account[*].id", "$.account[*].id"],
"purpose": "We need your bank account number for processing purposes",
"filter": {
"type": "string",
"minLength": 10,
"maxLength": 12
}
},
{
"path": ["$.credentialSubject.account[*].route", "$.vc.credentialSubject.account[*].route", "$.account[*].route"],
"purpose": "You must have an account with a German, US, or Japanese bank account",
"filter": {
"type": "string",
"pattern": "^DE|^US|^JP"
}
}
]
}
}
]
{
"id": "employment_input_xyz_gov",
"group": ["B"],
"schema": [
{
"uri": ["https://login.idp.com/xyz.gov/.well-known/openid-configuration"],
"name": "Verify XYZ Government Employment",
"purpose": "We need to know if you currently work at an agency in the XYZ government",
"metadata": {
"client_id": "40be4fb5-7f3a-470b-aa37-66ed43821bd7",
"redirect_uri": "https://tokens.xyz.gov/verify"
}
}
],
"constraints": {
"fields": [
{
"path": ["$.status"],
"filter": {
"type": "string",
"pattern": "active"
}
}
]
}
}
§ Input Descriptor Objects
Input Descriptors are objects that describe what type of input data/claim, or sub-fields thereof, is required for submission to the Verifier. Input Descriptor Objects are composed as follows:
- The object MUST contain an
id
property. The value of theid
property MUST be a unique identifying string that does not conflict with theid
of another Input Descriptor in the same Presentation Definition object. - The object MAY contain a
group
property, and if present, its value MUST match one of the grouping strings listed in thefrom
values of a Submission Requirement Rule Object. - The object MAY contain a
name
property, and if present its value SHOULD be a human-friendly name that describes what the target schema represents. - The object MAY contain a
purpose
property, and if present its value MUST be a string that describes the purpose for which the claim’s data is being requested. - The object MAY contain a
metadata
property, and if present its value MUST be an object with metadata properties that describe any information specific to the acquisition, formulation, or details of the claim in question. - The object MUST contain a
schema
property, and its value MUST be an array composed of objects as follows:- The object MUST contain a
uri
property, and its value MUST be an string consisting of a valid URI string for the acceptable claim schemas. Multiple array objects may be present for multiple schemas. A common use of multiple entries in theschema
array is when multiple versions of a claim schema exist and there is a desire to express support for more than one version. This field allowing multiple URIs is not intended to be used as a mechanism for including references to fundamentally different schemas, and SHOULD NOT be used by the implementer this way. - The object MAY contain a boolean
required
property, and if present andtrue
it signifies that the given schema object is required to fulfill the given Submission Requirement.
- The object MUST contain a
- The object MAY contain a
constraints
property, and its value MUST be an object composed as follows:-
The object MAY contain a
limit_disclosure
property, and if present its value MUST be a boolean value. Setting the property totrue
indicates that the processing entity SHOULD NOT submit any fields beyond those listed in thefields
array (if present). Setting the property tofalse
, or omitting the property, indicates the processing entity MAY submit a response that contains more than the data described in thefields
array. -
The object MAY contain a
statuses
property, and if present, its value MUST be an object that includes one or more of the following status properties:active
,suspended
,revoked
. These statuses are defined as follows:active
- a credential that is not revoked, expired, suspended, or in any type of deactivated state.suspended
- a credential is suspended if the Issuer has published an explicit signal that the credential is in an inactive state and should not currently be relied upon, but may become active again in the future.revoked
- a credential is revoked if the Issuer has published an explicit signal that the credential in question should not be relied upon going forward as an accurate reflection of the Issuer’s statements about the Subject within the scope of the credential.
"statuses": { "active": { "directive": "required" // other values: "allowed", "disallowed" }, "suspended": {...}, "revoked": {...} }
The values of all status properties are objects, composed as follows:
- Status objects MUST include a
directive
property, and its value MUST be one of the following strings:required
: the credential MUST be of the specified status.allowed
: the credential MAY be of the specified status.disallowed
: the credential MUST NOT be of the specified status.
-
The object MAY contain a
subject_is_issuer
property, and if present its value MUST be one of the following strings:required
- This indicates that the processing entity MUST submit a response that has been self-attested, i.e., the claim used in the presentation has been ‘issued’ by the subject of the claim.preferred
- This indicates that it is RECOMMENDED that the processing entity submit a response that has been self-attested, i.e., the claim used in the presentation has been ‘issued’ by the subject of the claim.
The
subject_is_issuer
property could be used by a Verifier to require that certain inputs be self_attested. For example, a college applicationpresentation definition
might contain an Input Descriptor object for an essay submission. In this case, the Verifier would be able to require that the essay be provided by the one submits the application. -
The object MAY contain an
is_holder
property, and if present its value MUST be an array of objects composed as follows:- The object MUST contain a
field_id
property. The value of this property MUST be an array of strings, with each string matching the string value from a Input Descriptor Field Entry object’sid
property. This identifies the attribute whose subject is of concern to the verifier. - The object MUST contain a
directive
property. The value of this property MUST be one of the following strings:required
- This indicates that the processing entity MUST include proof that the subject of each attribute identified by a value in thefield_id
array is the same as the entity submitting the response.preferred
- This indicates that it is RECOMMENDED that the processing entity include proof that the subject of each attribute identified by a value in thefield_id
array is the same as the entity submitting the response.
The
is_holder
property would be used by a Verifier to require that certain inputs be provided by a certain subject. For example, an identity verificationpresentation definition
might contain an Input Descriptor object for a birthdate from a birth certificate. In this case, the Verifier would be able to require that the holder of the birth certificate claim is the same as the subject of the birthdate attribute. This is especially useful in cases where a claim may have multiple subjects.For more information about techniques used to prove binding to a holder, please see Holder Binding.
- The object MUST contain a
-
The object MAY contain a
same_subject
property, and if present its value MUST be an array of objects composed as follows:- The object MUST contain a
field_id
property. The value of this property MUST be an array of strings, with each string matching the string value from a Input Descriptor Field Entry object’sid
property. This identifies the attributes whose subject is of concern to the verifier. It is important to note that the attributes MAY be identified in an Input Descriptor Field Entry of a different Input Descriptor object. - The object MUST contain a
directive
property. The value of this property MUST be one of the following strings:required
- This indicates that the processing entity MUST include proof that the subject of each attribute identified by a value in thefield_id
array is the same as the subject of the attributes identified by the other values in thefield_id
array.preferred
- This indicates that it is RECOMMENDED that the processing entity include proof that the subject of each attribute identified by a value in thefield_id
array is the same as the subject of the attributes identified by the other values in thefield_id
array.
The
same_subject
property would be used by a Verifier to require that certain provided inputs be about the same subject. For example, apresentation definition
might contain an Input Descriptor object which calls for a street address from a driver license claim and another Input Descriptor object which calls for a name from a birth certificate claim. The Verifier would be able to require that the subject of the street address attribute claim is the same as the subject of the name attribute. - The object MUST contain a
-
The object MAY contain a
fields
property, and its value MUST be an array of Input Descriptor Field Entry objects, each being composed as follows:-
The object MUST contain a
path
property, and its value MUST be an array of one or more JSONPath string expressions, as defined in the JSONPath Syntax Definition section, that select a target value from the input. The array MUST be evaluated from 0-index forward, and the first expressions to return a value will be used for the rest of the entry’s evaluation. The ability to declare multiple expressions this way allows the Verifier to account for format differences - for example: normalizing the differences in structure between JSON-LD/JWT-based Verifiable Credentials and vanilla JSON Web Tokens (JWTs) [RFC7797]. -
The object MAY contain an
id
property, and if present its value MUST be a string that is unique from any other field object’sid
property. -
The object MAY contain a
purpose
property, and if present its value MUST be a string that describes the purpose for which the field is being requested. -
The object MAY contain a
filter
property, and if present its value MUST be JSON Schema descriptor used to filter against the values returned from evaluation of the JSONPath string expressions in thepath
array. -
The object MAY contain a
predicate
property. If thepredicate
property is present, thefilter
property MUST also be present. The inclusion of thepredicate
property indicates that the processing entity returns a boolean, rather than a value returned from evaluation of the JSONPath string expressions in thepath
array. The boolean returned is the result of using thefilter
property’s JSON Schema descriptors against the evaluated value. The value ofpredicate
MUST be one of the following strings:required
- This indicates that the returned value MUST be the boolean result of applying the value of thefilter
property to the result of evaluating thepath
property.preferred
- This indicates that the returned value SHOULD be the boolean result of applying the value of thefilter
property to the result of evaluating thepath
property.
If the
predicate
property is present, the set of JSON Schema descriptors which comprise the value of thefilter
property MUST be restricted according to the desired predicate operation, as follows:- To express the following range proofs, use the JSON Schema
numeric range
properties:
greater-than
- Use theexclusiveMinimum
descriptor. For example, to request a proof that an attribute is greater than 10000:{ "type": "number", "exclusiveMinimum": 10000, }
less-than
- Use theexclusiveMaximum
descriptor. For example, to request a proof that an attribute is less than 85:{ "type": "number", "exclusiveMaximum": 85, }
greater-than or equal-to
- Use theminimum
descriptor. For example, to request a proof that an attribute is greater than or equal to 18:{ "type": "number", "minimum": 18, }
less-than or equal-to
- Use themaximum
descriptor. For example, to request a proof that an attribute is less than or equal to 65536:{ "type": "number", "maximum": 65536, }
- to express the following equality proofs, use the JSON Schema
const
descriptor:equal-to
- Use theconst
descriptor. For example to request proof that an attribute has the value “Chad”:{ "const": "Chad" }
not equal-to
- Use theconst
descriptor with thenot
operator. For example, to request proof that an attribute does not have the value “Karen”:{ "not": { "const": "Karen" } }
- to express set-membership proofs, use the JSON Schema
enum
descriptor:in-set
- Use theenum
descriptor. For example, to request proof that an attribute is contained in the set of rainbow colors:{ "type": "string", "enum": ["red", "yellow", "blue"] }
not-in-set
- Use theenum
descriptor with thenot
operator. For example, to request proof that an attribute is not contained in the set of primary colors:{ "not": { "enum": ["red", "yellow", "blue"] } }
At this time, additional predicate operations are not supported.
-
-
§ Input Evaluation
A consumer of a Presentation Definition must filter inputs they hold (signed claims, raw data, etc.) to determine whether they possess the inputs required to fulfill the demands of the Verifying party. A consumer of a Presentation Definition SHOULD use the following process to validate whether or not its candidate inputs meet the requirements it describes:
For each Input Descriptor in the input_descriptors
array of a Presentation
Definition, a User Agent should compare each candidate input (JWT,
Verifiable Credential, etc.) it holds to determine whether there is a match.
Evaluate each candidate input as follows:
- The schema of the candidate input must match one of the Input
Descriptor
schema
objecturi
values exactly. If the scheme is a hashlink or a similar value that points to immutable content, this means the content of the schema, not just the URI from which it is downloaded, must also match. If one of the values is an exact match, proceed, if there are no exact matches, skip to the next candidate input. - If the
constraints
property of the Input Descriptor is present, and it contains afields
property with one or more Input Descriptor Field Entries, evaluate each against the candidate input as follows:- Iterate the Input Descriptor
path
array of JSONPath string expressions from 0-index, executing each expression against the candidate input. Cease iteration at the first expression that returns a matching Field Query Result and use the result for the rest of the field’s evaluation. If no result is returned for any of the expressions, skip to the next candidate input. - If the
filter
property of the field entry is present, validate the Field Query Result from the step above against the JSON Schema descriptor value. - If the
predicate
property of the field entry is present, a boolean value should be returned rather than the value of the Field Query Result. Calculate this boolean value by evaluating the Field Query Result against the JSON Schema descriptor value of thefilter
property. - If the result is valid, proceed iterating the rest of the
fields
entries.
- Iterate the Input Descriptor
- If all of the previous validation steps are successful, mark the candidate
input as a match for use in a Presentation Submission, and if present at
the top level of the Input Descriptor, keep a relative reference to the
group
values the input is designated for. - If the
constraints
property of the Input Descriptor is present and it contains alimit_disclosure
property set to the boolean valuetrue
, ensure that any subsequent submission of data in relation to the candidate input is limited to the entries specified in thefields
property. If thefields
property is not present, or contains zero Input Descriptor Field Entries, submission SHOULD NOT include any claim data from the claim. (for example: a Verifier may simply want to know a Holder has a valid, signed claims of a particular type, without disclosing any of the data it contains). - If the
constraints
property of the Input Descriptor is present, and it contains asubject_is_issuer
property set to the valuerequired
, ensure that any submission of data in relation to the candidate input is fulfilled using a self_attested claim. - If the
constraints
property of the Input Descriptor is present, and it contains anis_holder
property, ensure that for each object in the array, any submission of data in relation to the candidate input is fulfilled by the subject of the attributes so identified by the strings in thefield_id
array. - If the
constraints
property of the Input Descriptor is present, and it contains asame_subject
property, ensure that for each object in the array, all of the attributes so identified by the strings in thefield_id
array are about the same subject.
The above evaluation process assumes the User Agent will test each candidate
input (JWT, Verifiable Credential, etc.) it holds to determine if it meets the
criteria for inclusion in submission. Any additional testing of a candidate
input for a schema match beyond comparison of the schema uri
(e.g. specific
requirements or details expressed in schema metadata
) is at the discretion
of the implementer.
§ Expired and Revoked Data
Certain types of claims have concepts of expiration and revocation. Expiration is mechanism normally used to communicate a time bound up until which a claim is valid. Revocation is a mechanism normally used to give an issuer control over the status of a claim after issuance. Different claim specifications handle these concepts in different ways.
Presentation Definitions
have a need to specify whether expired, revoked,
or claims of other statuses can be accepted. For claims that have
simple status properties Input Descriptor Filters
JSON Schema can be used to write specify acceptable criteria.
The first example demonstrates expiry using the VC Data Model’s
expirationDate
property.
The second demonstrates revocation, or more generally, credential status
using the VC Data Model’s credentialStatus
property.
Using the syntax provided in the example a Verifier will have all requisite
information to resolve the status of a claim.
{
"id": "drivers_license_information",
"name": "Verify Valid License",
"purpose": "We need to know you have a license valid through December.",
"metadata": {
"client_id": "4fb540be-3a7f-0b47-bb37-3821bd766ed4",
"redirect_uri": "https://yourwatchful.gov/verify"
},
"schema": [
{
"uri": "https://yourwatchful.gov/drivers-license-schema.json",
"required": true
}
],
"constraints": {
"fields": [
{
"path": ["$.expirationDate"],
"filter": {
"type": "string",
"format": "date-time",
"min": "2020-12-31T23:59:59.000Z"
}
}
]
}
}
{
"id": "drivers_license_information",
"name": "Verify Valid License",
"purpose": "We need to know that your license has not been revoked.",
"metadata": {
"client_id": "4fb540be-3a7f-0b47-bb37-3821bd766ed4",
"redirect_uri": "https://yourwatchful.gov/verify"
},
"schema": [
{
"uri": "https://yourwatchful.gov/drivers-license-schema.json"
}
],
"constraints": {
"fields": [
{
"path": ["$.credentialStatus"]
}
]
}
}
§ Holder Binding
Credentials often rely on proofs of holder binding for their validity. A verifier may wish to determine that a particular claim, or set of claims is bound to the claim holder. This can help the verifier to determine the legitimacy of the presented proofs. Some examples of holder binding include proof of identifier control, proof the holder knows a secret, or biometrics.
The claim issuer makes proofs of holder binding possible by including holder information either in the claim or the claim signature.
§ Proof of Identifier Control
A number of claim types include an identifier for the claim subject. A verifier may wish to ascertain that one of the subject identified in the claim is the one submitting the proof, or has consented to the proof submission. A claim may also include an identifier for the holder, independent of the subject identifiers.
One mechanism for providing such proofs is the use of a DID as the identifier for the claim subject or holder. DIDs enable an entity to provide a cryptographic proof of control of the identifier, usually through a demonstration that the holder knows some secret value, such as a private key. The holder can demonstrate the same proof of control when presenting the claim. In addition to verifying the authenticity and origin of the claim itself, a verifier can verify that the holder of the claim still controls the identifier.
§ Link Secrets
Some claim signatures support the inclusion of holder-provided secrets that become incorporated into the signature, but remain hidden from the claim issuer. One common use of this capability is to bind the claim to the holder. This is sometimes called a link secret. Just as with proof of control of an identifier, link secret proofs demonstrate that the holder knows some secret value. Upon presentation to a verifier, the holder demonstrates knowledge of the secret without revealing it. The verifier can verify that the holder knows the link secret, and that the link secret is contained in the claim signature.
§ Biometrics
This type of holder binding, instead of relying on demonstrating knowledge of some secret value, relies on the evaluation of biometric data. There are a number of mechanisms for safely embedding biometric information in a claim such that only a person who can confirm the biometric may present the claim.
§ JSON Schema
The following JSON Schema Draft 7 definition summarizes the format-related rules above:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"schema": {
"type": "object",
"properties": {
"uri": { "type": "string" },
"required": { "type": "boolean" }
},
"required": ["uri"],
"additionalProperties": false
},
"filter": {
"type": "object",
"properties": {
"type": { "type": "string" },
"format": { "type": "string" },
"pattern": { "type": "string" },
"minimum": { "type": ["number", "string"] },
"minLength": { "type": "integer" },
"maxLength": { "type": "integer" },
"exclusiveMinimum": { "type": ["number", "string"] },
"exclusiveMaximum": { "type": ["number", "string"] },
"maximum": { "type": ["number", "string"] },
"const": { "type": ["number", "string"] },
"enum": {
"type": "array",
"items": { "type": ["number", "string"] }
},
"not": {
"type": "object",
"minProperties": 1
}
},
"required": ["type"],
"additionalProperties": false
},
"format": {
"type": "object",
"patternProperties": {
"^jwt$|^jwt_vc$|^jwt_vp$": {
"type": "object",
"properties": {
"alg": {
"type": "array",
"minItems": 1,
"items": { "type": "string" }
}
},
"required": ["alg"],
"additionalProperties": false
},
"^ldp_vc$|^ldp_vp$|^ldp$": {
"type": "object",
"properties": {
"proof_type": {
"type": "array",
"minItems": 1,
"items": { "type": "string" }
}
},
"required": ["proof_type"],
"additionalProperties": false
},
"additionalProperties": false
},
"additionalProperties": false
},
"submission_requirements": {
"type": "object",
"oneOf": [
{
"properties": {
"name": { "type": "string" },
"purpose": { "type": "string" },
"rule": {
"type": "string",
"enum": ["all", "pick"]
},
"count": { "type": "integer", "minimum": 1 },
"min": { "type": "integer", "minimum": 0 },
"max": { "type": "integer", "minimum": 0 },
"from": { "type": "string" }
},
"required": ["rule", "from"],
"additionalProperties": false
},
{
"properties": {
"name": { "type": "string" },
"purpose": { "type": "string" },
"rule": {
"type": "string",
"enum": ["all", "pick"]
},
"count": { "type": "integer", "minimum": 1 },
"min": { "type": "integer", "minimum": 0 },
"max": { "type": "integer", "minimum": 0 },
"from_nested": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/submission_requirements"
}
}
},
"required": ["rule", "from_nested"],
"additionalProperties": false
}
]
},
"input_descriptors": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"purpose": { "type": "string" },
"metadata": { "type": "object" },
"group": {
"type": "array",
"items": { "type": "string" }
},
"schema": {
"type": "array",
"items": { "$ref": "#/definitions/schema" }
},
"constraints": {
"type": "object",
"properties": {
"limit_disclosure": { "type": "boolean" },
"statuses": {
"type": "object",
"properties": {
"active": {
"type": "object",
"properties": {
"directive": {
"type": "string",
"enum": ["required", "allowed", "disallowed"]
}
}
},
"suspended": {
"type": "object",
"properties": {
"directive": {
"type": "string",
"enum": ["required", "allowed", "disallowed"]
}
}
},
"revoked": {
"type": "object",
"properties": {
"directive": {
"type": "string",
"enum": ["required", "allowed", "disallowed"]
}
}
}
}
},
"fields": {
"type": "array",
"items": { "$ref": "#/definitions/field" }
},
"subject_is_issuer": {
"type": "string",
"enum": ["required", "preferred"]
},
"is_holder": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field_id": {
"type": "array",
"items": { "type": "string" }
},
"directive": {
"type": "string",
"enum": ["required", "preferred"]
}
},
"required": ["field_id", "directive"],
"additionalProperties": false
}
},
"same_subject": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field_id": {
"type": "array",
"items": { "type": "string" }
},
"directive": {
"type": "string",
"enum": ["required", "preferred"]
}
},
"required": ["field_id", "directive"],
"additionalProperties": false
}
}
},
"additionalProperties": false
}
},
"required": ["id", "schema"],
"additionalProperties": false
},
"field": {
"type": "object",
"oneOf": [
{
"properties": {
"id": { "type": "string" },
"path": {
"type": "array",
"items": { "type": "string" }
},
"purpose": { "type": "string" },
"filter": { "$ref": "#/definitions/filter" }
},
"required": ["path"],
"additionalProperties": false
},
{
"properties": {
"id": { "type": "string" },
"path": {
"type": "array",
"items": { "type": "string" }
},
"purpose": { "type": "string" },
"filter": { "$ref": "#/definitions/filter" },
"predicate": {
"type": "string",
"enum": ["required", "preferred"]
}
},
"required": ["path", "filter", "predicate"],
"additionalProperties": false
}
]
}
},
"type": "object",
"properties": {
"presentation_definition": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"purpose": { "type": "string" },
"locale": { "type": "string" },
"format": { "$ref": "#/definitions/format"},
"submission_requirements": {
"type": "array",
"items": {
"$ref": "#/definitions/submission_requirements"
}
},
"input_descriptors": {
"type": "array",
"items": { "$ref": "#/definitions/input_descriptors" }
}
},
"required": ["id", "input_descriptors"],
"additionalProperties": false
}
}
}
§ Presentation Requests
Presentation Definitions may be sent from a Verifier to a Holder using
a wide variety of transport mechanisms or claim exchange protocols. This
specification does not define a transport mechanism for Presentation Definitions
(or Presentation Request), but does note that different
use cases, supported signature schemes, protocols, and threat models may
require a Presentation Requestto have certain properties:
- Signature verification - A Holder may wish to have assurances as to the provenance, identity, or status of a Presentation Definition. In this case, a Presentation Request that uses digital signatures may be required.
domain
,challenge
, ornonce
- Some presentation protocols may require that presentations be unique, i.e., it should be possible for a Verifier to detect if a presentation has been used before. Other protocols may require that a presentation to be bound to a particular communication exchange, or session. In these cases, a Presentation Request that provides adomain
,challenge
,ornonce
property may be required.
§ Presentation Submission
Presentation Submissions are objects embedded within target claim
negotiation formats that unify the presentation of proofs to a Verifier
in accordance with the requirements a Verifier specified in a
Presentation Definition. Embedded Presentation Submission
objects MUST be located within target data format as a
presentation_submission
property, which are composed and embedded as follows:
- The
presentation_submission
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 object MUST include
id
anddefinition_id
properties.- The
id
property exists to uniquely identify the resource. The property MUST be a unique identifier, such as a UUID. - The
definition_id
property exists to link the submission to its definition and MUST be theid
value of a valid Presentation Definition.
- The
- The object MUST include a
descriptor_map
property, and its value MUST be an array of Input Descriptor Mapping Objects, each being composed as follows:- The object MUST include an
id
property, and its value MUST be a string matching theid
property of the Input Descriptor in the Presentation Definition the submission is related to. - The object MUST include a
format
property, and its value MUST be a string value matching one of the Claim Format Designation (jwt
,jwt_vc
,jwt_vp
,ldp_vc
,ldp_vp
,ldp
), to denote what data format the claim is being submitted in. - The object MUST include a
path
property, and its value MUST be a JSONPath string expression that selects the claim to be submit in relation to the identified Input Descriptor identified, when executed against the top-level of the object the Presentation Submission is embedded within. - The object MAY include a
path_nested
object to specify the presence of a multi-claim envelope format, meaning the claim indending to be selected must 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 object MUST include an
§ Processing of path_nested
Entries
Example Nested Submission
{
"presentation_submission": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"definition_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"descriptor_map": [
{
"id": "banking_input_2",
"format": "jwt_vp",
"path": "$.outerClaim[0]",
"path_nested": {
"id": "banking_input_2",
"format": "ldp_vc",
"path": "$.innerClaim[1]",
"path_nested": {
"id": "banking_input_2",
"format": "jwt_vc",
"path": "$.mostInnerClaim[2]"
}
}
}
]
}
When the path_nested
property is present in a Presentation Submission object,
process as follows:
- For each Nested Submission Traversal Object in the
path_nested
array, process as follows: a. Execute the JSONPath expression string on the Current Traversal Object, or if none is designated, the top level of the Embed Target. b. Decode and parse the value returned from JSONPath execution in accordance with the Claim Format Designation specified in the object’sformat
property. If value parses and validates in accordance with the Claim Format Designation specified, let the resulting object be the Current Traversal Object c. If present, process the next Nested Submission Traversal Object in the currentpath_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 Input Descriptor indicated by theid
property of the containing Input Descriptor Mapping Object.
§ Limited Disclosure Submissions
If for all claims submitted in relation to
Input Descriptor Objects that include a
constraints
object with a limit_disclosure
property set to the boolean value
true
, ensure that the data submitted is limited to the entries specified in
the fields
property of the constraints
object. If the fields
property
is not present, or contains zero
Input Descriptor Field Entries, the
submission SHOULD NOT include any claim data from the claim. (for
example: a Verifier may simply want to know a Holder has a valid, signed
claim of a particular type, without disclosing any of the data it contains).
§ Validation of Claims
Once a claim has been ingested via a Presentation Submission, any validation beyond the process of evaluation defined by the Input Evaluation section is outside the scope of Presentation Exchange. Validation of signatures and other cryptographic proofs are a function of a given claim format, and should be evaluated in accordance with a given claim format’s standardized processing steps. Additional verification of claim data or subsequent validation required by a given Verifier are left to the Verifier’s systems, code and business processes to define and execute.
During validation, each Input Descriptor Object MUST refer to only a single discrete container within a Presentation Submission, such that all checks refer to properties within the same container and are protected by the same digital signature, if the container format supports digital signatures. Examples of discrete container formats include a single Verifiable Credential within a Verifiable Presentation as defined in W3C Verifiable Credentials, OpenID Connect Tokens, and JSON Web Tokens. This is to ensure that related requirements, for example, “given name” and “family name” within the same Input Descriptor Object also come from the same container.
§ Embed Targets
The following section details where the Presentation Submission 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 presentation_submission
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 |
---|---|
OpenID | top-level |
DIDComms | $.presentations~attach.data.json |
VP | top-level |
CHAPI | $.data |
§ JSON Schema
The following JSON Schema Draft 7 definition summarizes the rules above:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Presentation Submission",
"type": "object",
"properties": {
"presentation_submission": {
"type": "object",
"properties": {
"id": { "type": "string" },
"definition_id": { "type": "string" },
"locale": { "type": "string" },
"descriptor_map": {
"type": "array",
"items": { "$ref": "#/definitions/descriptor" }
}
},
"required": ["id", "definition_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": ["presentation_submission"],
"additionalProperties": false
}
§ Claim Format Designations
Within the Presentation Exchange specification, there are numerous sections where Verifiers and Holders convey what claim variants they support and are submitting. The following are the normalized references used within the specification:
jwt
- the format is a JSON Web Token (JWTs) [RFC7797] that will be submitted in the form of a JWT encoded string. Expression of supported algorithms in relation to this format MUST be conveyed using analg
property paired with values that are identifiers from the JSON Web Algorithms registry [RFC7518].jwt_vc
,jwt_vp
- these formats are JSON Web Tokens (JWTs) [RFC7797] that will be submitted in the form of a JWT encoded string, and the body of the decoded JWT string is defined in the JSON Web Token (JWT) [RFC7797] section of the W3C Verifiable Credentials specification. Expression of supported algorithms in relation to these formats MUST be conveyed using analg
property paired with values that are identifiers from the JSON Web Algorithms registry [RFC7518].ldp_vc
,ldp_vp
- these formats are W3C Verifiable Credentials [VC-DATA-MODEL] that will be submitted in the form of a JSON object. Expression of supported algorithms in relation to these formats MUST be conveyed using aproof_type
property paired with values that are identifiers from the Linked Data Cryptographic Suite Registry.ldp
- this format is defined in the W3C CCG Linked Data Proofs specification [[spec: Linked Data Proofs]], and will be submitted as objects. Expression of supported algorithms in relation to these formats MUST be conveyed using aproof_type
property with values that are identifiers from the Linked Data Cryptographic Suite Registry.
§ JSON Schema Vocabulary Definition
The Presentation Exchange specification adopts and defines the following JSON Schema data format and processing variant, which implementers MUST support for evaluation of the portions of the Presentation Exchange specification that call for JSON Schema validation: https://tools.ietf.org/html/draft-handrews-json-schema-02
§ JSONPath Syntax Definition
The Presentation Exchange specification adopts and defines the following syntax from the JSONPath object query language, which implementers MUST support for evaluation of the portions of the Presentation Exchange specification that call for JSONPath expression execution.
JSONPath | Description |
---|---|
$ |
The root object/element |
@ |
The current object/element |
. |
Child member operator |
.. |
Recursive descendant operator; JSONPath borrows this syntax from E4X |
* |
Wildcard matching all objects/elements regardless their names |
[] |
Subscript operator |
[,] |
Union operator for alternate names or array indices as a set |
[start:end:step] |
Array slice operator borrowed from ES4 / Python |
?() |
Applies a filter (script) expression via static evaluation |
() |
Script expression via static evaluation |
Example JSON Object
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
}, {
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}, {
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}, {
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
Example JSONPath Expressions
JSONPath | Description |
---|---|
$.store.book[*].author |
The authors of all books in the store |
$..author |
All authors |
$.store.* |
All things in store, which are some books and a red bicycle |
$.store..price |
The price of everything in the store |
$..book[2] |
The third book |
$..book[(@.length-1)] |
The last book via script subscript |
$..book[-1:] |
The last book via slice |
$..book[0,1] |
The first two books via subscript union |
$..book[:2] |
The first two books via subscript array slice |
$..book[?(@.isbn)] |
Filter all books with isbn number |
$..book[?(@.price<10)] |
Filter all books cheaper than 10 |
$..book[?(@.price==8.95)] |
Filter all books that cost 8.95 |
$..book[?(@.price<30 && @.category=="fiction")] |
Filter all fiction books cheaper than 30 |
$..* |
All members of JSON structure |
§ External References
- RFC7518
- JSON Web Algorithms (JWA). M. Jones; 2015-05. Status: Proposed Standard.
- RFC7797
- JSON Web Signature (JWS) Unencoded Payload Option. M. Jones; 2016-02. Status: Proposed Standard.
- VC-DATA-MODEL
- Verifiable Credentials Data Model 1.0. Manu Sporny; Grant Noble; Dave Longley; Daniel Burnett; Brent Zundel; 2019-11-19. Status: REC.
§ Appendix
§ Embed Target Examples
§ Presentation Submissions
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/presentation-exchange/submission/v1"
],
"type": [
"VerifiablePresentation",
"PresentationSubmission"
],
"presentation_submission": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"definition_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"descriptor_map": [
{
"id": "banking_input_2",
"format": "jwt_vc",
"path": "$.verifiableCredential[0]"
},
{
"id": "employment_input",
"format": "ldp_vc",
"path": "$.verifiableCredential[1]"
},
{
"id": "citizenship_input_1",
"format": "ldp_vc",
"path": "$.verifiableCredential[2]"
}
]
},
"verifiableCredential": [
{ // DECODED JWT PAYLOAD, ASSUME THIS WILL BE A BIG UGLY OBJECT
"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": "..."
}
}
{
"iss": "https://self-issued.me",
"sub": "248289761001",
"preferred_username": "superman445",
"presentation_submission": {
"id": "a30e3b91-fb77-4d22-95fa-871689c322e2",
"definition_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"descriptor_map": [
{
"id": "banking_input_2",
"format": "jwt",
"path": "$._claim_sources.banking_input_2.JWT"
},
{
"id": "employment_input",
"format": "jwt_vc",
"path": "$._claim_sources.employment_input.VC_JWT"
},
{
"id": "citizenship_input_1",
"format": "ldp_vc",
"path": "$._claim_sources.citizenship_input_1.VC"
}
]
},
"_claim_names": {
"verified_claims": [
"banking_input_2",
"employment_input",
"citizenship_input_1"
]
},
"_claim_sources": {
"banking_input_2": {
"JWT": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwcz
ovL3NlcnZlci5vdGhlcm9wLmNvbSIsInN1YiI6ImU4MTQ4NjAzLTg5MzQtNDI0N
S04MjViLWMxMDhiOGI2Yjk0NSIsInZlcmlmaWVkX2NsYWltcyI6eyJ2ZXJpZmlj
YXRpb24iOnsidHJ1c3RfZnJhbWV3b3JrIjoiaWFsX2V4YW1wbGVfZ29sZCJ9LCJ
jbGFpbXMiOnsiZ2l2ZW5fbmFtZSI6Ik1heCIsImZhbWlseV9uYW1lIjoiTWVpZX
IiLCJiaXJ0aGRhdGUiOiIxOTU2LTAxLTI4In19fQ.FArlPUtUVn95HCExePlWJQ
6ctVfVpQyeSbe3xkH9MH1QJjnk5GVbBW0qe1b7R3lE-8iVv__0mhRTUI5lcFhLj
oGjDS8zgWSarVsEEjwBK7WD3r9cEw6ZAhfEkhHL9eqAaED2rhhDbHD5dZWXkJCu
XIcn65g6rryiBanxlXK0ZmcK4fD9HV9MFduk0LRG_p4yocMaFvVkqawat5NV9QQ
3ij7UBr3G7A4FojcKEkoJKScdGoozir8m5XD83Sn45_79nCcgWSnCX2QTukL8Ny
wIItu_K48cjHiAGXXSzydDm_ccGCe0sY-Ai2-iFFuQo2PtfuK2SqPPmAZJxEFrF
oLY4g"
},
"employment_input": {
"VC": {
"@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": "..."
}
}
},
"citizenship_input_1": {
"VC": {
"@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": "EcdsaSecp256k1VerificationKey2019",
"created": "2017-06-18T21:19:10Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "https://example.edu/issuers/keys/1",
"jws": "..."
}
}
}
}
}
{
"type": "web",
"dataType": "VerifiablePresentation",
"data": {
// Presentation Submission goes here
}
}
{
"@type": "https://didcomm.org/present-proof/%VER/presentation",
"@id": "f1ca8245-ab2d-4d9c-8d7d-94bf310314ef",
"comment": "some comment",
"formats" : [{
"attach_id" : "2a3f1c4c-623c-44e6-b159-179048c51260",
"format" : "dif/presentation-exchange/[email protected]"
}],
"presentations~attach": [{
"@id": "2a3f1c4c-623c-44e6-b159-179048c51260",
"mime-type": "application/ld+json",
"data": {
"json": {
// Presentation Submission goes here
}
}
}]
}
§ Developer Resources
§ JSONPath
- Node.js
- Java
- Kotlin
- Python
- Go
§ JSON Schema
- Node.js
- Java
- .NET
- Kotlin
- Python
- Rust
- Go
§ IANA Considerations
§ JSON Web Token Claims Registration
This specification registers the claims in section Registry Contents in the IANA JSON Web Token Claims registry defined in RFC 751 JSON Web Token (JWT).
§ Registry Contents
Presentation Definition | Values |
---|---|
Claim Name: | presentation_definition |
Claim Description: | Presentation Definition |
Change Controller: | DIF Claims & Credentials - Working Group - https://github.com/decentralized-identity/claims-credentials/blob/main/CODEOWNERS |
Specification Document(s): | Section 5 of this document |
Presentation Submission | Values |
---|---|
Claim Name: | presentation_submission |
Claim Description: | Presentation Submission |
Change Controller: | DIF Claims & Credentials - Working Group - https://github.com/decentralized-identity/claims-credentials/blob/main/CODEOWNERS |
Specification Document(s): | Section 6 of this document |