§ Presentation Exchange

Specification Status: Strawman

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 credential format and transport envelope agnostic, meaning an implementer can use JWTs, VCs, JWT-VCs, or any other credential format, and convey them via OIDC, DIDComm, CHAPI, 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

Term Definition
Decentralized Identifier (DID) Unique ID 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.

§ 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.

EXAMPLE
{
  "presentation_definition": {
    "locale": "en-US",
    "input_descriptors": [{
      "id": "name_input",
      "schema": {
        "uri": ["https://name-standards.com/name.json"],
        "name": "Full Legal Name",
        "purpose": "We need your full legal name."
      }
    }]
  }
}
EXAMPLE
{
  "presentation_submission": {
    "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.

EXAMPLE
{
  // VP, OIDC, DIDComm, or CHAPI outer wrapper

  "presentation_definition": {
    "input_descriptors": [
      {
        "id": "banking_input",
        "schema": {
          "uri": ["https://bank-standards.com/customer.json"],
          "name": "Bank Account Information",
          "purpose": "We need your bank and account information."
        },
        "constraints": {
          "limit_disclosure": true,
          "fields": [
            {
              "path": ["$.issuer", "$.vc.issuer", "$.iss"],
              "purpose": "The credential must be from one of the specified issuers",
              "filter": {
                "type": "string",
                "pattern": "did:example:123|did:example:456"
              }
            }
          ]
        }
      },
      {
        "id": "citizenship_input",
        "schema": {
          "uri": ["hub://did:foo:123/Collections/schema.us.gov/passport.json"],
          "name": "US Passport"
        },
        "constraints": {
          "fields": [
            {
              "path": ["$.credentialSubject.birth_date", "$.vc.credentialSubject.birth_date", "$.birth_date"],
              "filter": {
                "type": "string",
                "format": "date",
                "minimum": "1999-5-16"
              }
            }
          ]
        }

      }
    ]
  }
}
EXAMPLE
{
  // VP, OIDC, DIDComm, or CHAPI outer wrapper

  "presentation_definition": {
    "submission_requirements": [{
      "name": "Citizenship Information",
      "rule": "pick",
      "count": 1,
      "from": "A"
    }],
    "input_descriptors": [
      {
        "id": "citizenship_input_1",
        "group": ["A"],
        "schema": {
          "uri": ["https://eu.com/claims/DriversLicense.json"],
          "name": "EU Driver's License"
        },
        "constraints": {
          "fields": [
            {
              "path": ["$.issuer", "$.vc.issuer", "$.iss"],
              "purpose": "The credential 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-5-16"
              }
            }
          ]
        }
      },
      {
        "id": "citizenship_input_2",
        "group": ["A"],
        "schema": {
          "uri": ["hub://did:foo:123/Collections/schema.us.gov/passport.json"],
          "name": "US Passport"
        },
        "constraints": {
          "fields": [
            {
              "path": ["$.credentialSubject.birth_date", "$.vc.credentialSubject.birth_date", "$.birth_date"],
              "filter": {
                "type": "string",
                "format": "date",
                "maximum": "1999-5-16"
              }
            }
          ]
        }
      }
    ]
  }
}
EXAMPLE
{
  // VP, OIDC, DIDComm, or CHAPI outer wrapper
  
  "presentation_definition": {
    "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",
        "group": ["A"],
        "schema": {
          "uri": ["https://bank-standards.com/customer.json"],
          "name": "Bank Account Information",
          "purpose": "We need your bank and account information."
        },
        "constraints": {
          "limit_disclosure": true,
          "fields": [
            {
              "path": ["$.issuer", "$.vc.issuer", "$.iss"],
              "purpose": "The credential 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",
        "group": ["A"],
        "schema": {
          "uri": [
            "https://bank-schemas.org/1.0.0/accounts.json",
            "https://bank-schemas.org/2.0.0/accounts.json"
          ],
          "name": "Bank Account Information",
          "purpose": "We need your bank and account information."
        },
        "constraints": {
          "fields": [
            {
              "path": ["$.issuer", "$.vc.issuer", "$.iss"],
              "purpose": "The credential 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",
        "group": ["B"],
        "schema": {
          "uri": ["https://business-standards.org/schemas/employment-history.json"],
          "name": "Employment History",
          "purpose": "We need to know your work history."
        },
        "constraints": {
          "fields": [
            {
              "path": ["$.jobs[*].active"],
              "filter": {
                "type": "boolean",
                "pattern": "true"
              }
            }
          ]
        }
      },
      {
        "id": "citizenship_input_1",
        "group": ["C"],
        "schema": {
          "uri": ["https://eu.com/claims/DriversLicense.json"],
          "name": "EU Driver's License"
        },
        "constraints": {
          "fields": [
            {
              "path": ["$.issuer", "$.vc.issuer", "$.iss"],
              "purpose": "The credential 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",
        "group": ["C"],
        "schema": {
          "uri": ["hub://did:foo:123/Collections/schema.us.gov/passport.json"],
          "name": "US Passport"
        },
        "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:

§ 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. credential 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.

All members of the submission_requirements array MUST be satisfied.

EXAMPLE
  "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:

  1. 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.
  2. The object MUST contain either a from 'or from_nested property. If both properties are present, the implementation MUST produce an error. The values of the from and from_nested properties are defined as follows:
    • from - the value of the from property must be a group string matching one of the group strings specified for one or more Input Descriptor objects.
    • from_nested - an array of nested Submission Requirement Objects.
  3. 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.
  4. 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.
  5. The object MAY contain additional properties as required by Submission Requirement Rules, such as count, min, and max 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
EXAMPLE
  "submission_requirements": [
    {
      "name": "Submission of educational transcripts",
      "purpose": "We need all your educational transcripts to process your application",
      "rule": "all",
      "from": "A"
    }
  ]
§ pick rule

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":

EXAMPLE
  "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"
    }
  ]
EXAMPLE
  "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":

EXAMPLE
  "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" },
            "count": { "type": "integer", "minimum": 1 },
            "from": { "type": "string" }
          },
          "required": ["rule", "from"],
          "additionalProperties": false
        },
        {
          "properties": {
            "name": { "type": "string" },
            "purpose": { "type": "string" },
            "rule": { "type": "string" },
            "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:

  1. The rule property value may be either "all" or "pick", and the implementation MUST produce an error if an unknown rule value is present.
  2. The Submission Requirement MUST contain a from property or a from_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.
  3. To determine whether a Submission Requirement is satisfied, used the following algorithm:
    • If the rule is "all", then the Submission Requirement MUST contain a from property or a from_nested property, and of whichever are present, all inputs from the from group string specified or Submission Requirements in the from_nested array MUST be submitted or satisfied, respectively.
    • If the rule is "pick", then the Submission Requirement MUST contain a from property or a from_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 of count 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 the min 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 the max property.

§ Input Descriptors

Input Descriptors are objects used to describe the information a Verifier requires of a Holder before they will proceed with an interaction. 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:

EXAMPLE
"input_descriptors": [
  {
    "id": "banking_input_1",
    "group": ["A"],
    "schema": {
      "uri": [
        "https://bank-schemas.org/1.0.0/accounts.json",
        "https://bank-schemas.org/2.0.0/accounts.json"
      ],
      "name": "Bank Account Information",
      "purpose": "We need your bank and account information."
    },
    "constraints": {
      "fields": [
        {
          "path": ["$.issuer", "$.vc.issuer", "$.iss"],
          "purpose": "The credential 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"
          }
        }
      ]
    }
  }
]
EXAMPLE
{
  "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/credential, 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 the id property MUST be a unique identifying string that does not conflict with the id 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 the from values of a Requirement Rule Object.
  • The object MUST contain a schema property, and its value MUST be an object composed as follows:
    • The object MUST contain a uri property, and its value MUST be an array consisting of one or more valid URI strings for the acceptable credential schemas. A common use of multiple entries in the uri array is when multiple versions of a credential 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 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 credential’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 credential in question.
  • 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 to true indicates that the processing entity SHOULD NOT submit any fields beyond those listed in the fields array (if present). Setting the property to false, or omitting the property, indicates the processing entity MAY submit a response that contains more than the data described in the fields array.
    • 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 some subset of values from the target 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).
      • 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 the path array.

§ Input Evaluation

A consumer of a Presentation Definition must filter inputs they hold (signed credentials, 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:

  1. The schema of the candidate input must match one of the Input Descriptor schema object uri 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.
  2. If the constraints property of the Input Descriptor is present, and it contains a fields property with one or more Input Descriptor Field Entries, evaluate each against the candidate input as follows:
    1. 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.
    2. 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.
    3. If the result is valid, proceed iterating the rest of the fields entries.
  3. 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.
  4. If the constraints property of the Input Descriptor is present and it contains a limit_disclosure property set to the boolean value true, ensure that any subsequent submission of data in relation to the candidate input is limited to the entries specified in the fields property. If the fields property is not present, or contains zero Input Descriptor Field Entries, submission SHOULD NOT include any claim data from the credential. (for example: a Verifier may simply want to know a Holder has a valid, signed credential of a particular type, without disclosing any of the data it contains).
NOTE

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.

§ JSON Schema

The following JSON Schema Draft 7 definition summarizes 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" },
            "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" },
            "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" },
        "group": {
          "type": "array",
          "items": { "type": "string" }
        },
        "schema": {
          "type": "object",
          "properties": {
            "uri": {
              "type": "array",
              "items": { "type": "string" }
            },
            "name": { "type": "string" },
            "purpose": { "type": "string" },
            "metadata": { "type": "string" }
          },
          "required": ["uri", "name"],
          "additionalProperties": false
        },
        "constraints": {
          "type": "object",
          "properties": {
            "limit_disclosure": { "type": "boolean" },
            "fields": {
              "type": "array",
              "items": { "$ref": "#/definitions/field" }
            }
          },
          "additionalProperties": false
        }
      },
      "required": ["id", "schema"],
      "additionalProperties": false
    },
    "field": {
      "type": "object",
      "properties": {
        "path": {
          "type": "array",
          "items": { "type": "string" }
        },
        "purpose": { "type": "string" },
        "filter": {
          "type": "object",
          "properties": {
            "type": { "type": "string" },
            "format": { "type": "string" },
            "pattern": { "type": "string" },
            "minimum": { "type": "string" },
            "minLength": { "type": "integer" },
            "maxLength": { "type": "integer" }
          },
          "required": ["type"],
          "additionalProperties": false
        }
      },
      "required": ["path"],
      "additionalProperties": false
    }
  },
  "type": "object",
  "properties": {
    "presentation_definition": {
      "type": "object",
      "properties": {
        "locale": { "type": "string" },
        "submission_requirements": {
          "type:": "array",
          "items": {
            "$ref": "#/definitions/submission_requirements"
          }
        },
        "input_descriptors": {
          "type:": "array",
          "items": { "$ref": "#/definitions/input_descriptors" }
        }
      },
      "required": ["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 credentials 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 Request to 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, or nonce - 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 a domain, challenge,or nonce property may be required.

§ Presentation Submission

Presentation Submissions are objects embedded within target credential 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 as follows:

  • 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 the id property of the Input Descriptor in the Presentation Definition the submission is related to.
    • The object MUST include a path property, and its value MUST be a JSONPath string expression that selects the credential 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.

If for all credentials 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 credential. (for example: a Verifier may simply want to know a Holder has a valid, signed credential of a particular type, without disclosing any of the data it contains).

§ Validation of Credentials

Once a credential 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 credential format, and should be evaluated in accordance with a given credential format’s standardized processing steps. Additional verification of credential data or subsequent validation required by a given Verifier are left to the Verifier’s systems, code and business processes to define and execute.

§ 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 credentials within the target data structure.

EXAMPLE
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://identity.foundation/presentation-exchange/submission/v1"
  ],
  "type": [
    "VerifiablePresentation",
    "PresentationSubmission"
  ],
  "presentation_submission": {
    "descriptor_map": [
      {
        "id": "banking_input_2",
        "path": "$.verifiableCredential.[0]"
      },
      {
        "id": "employment_input",
        "path": "$.verifiableCredential.[1]"
      },
      {
        "id": "citizenship_input_1",
        "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": "..."
  }
}
EXAMPLE
{
  "iss": "https://self-issued.me",
  "sub": "248289761001",
  "preferred_username": "superman445",
  "presentation_submission": {
    "descriptor_map": [
      {
        "id": "banking_input_2",
        "path": "$._claim_sources.banking_input_2.JWT"
      },
      {
        "id": "employment_input",
        "path": "$._claim_sources.employment_input.VC_JWT"
      },
      {
        "id": "citizenship_input_1",
        "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": "..."
        }
      }
    }
  }
}
EXAMPLE
{
  "type": "web",
  "dataType": "VerifiablePresentation",
  "data": {
    // Presentation Submission goes here
  }
}
EXAMPLE
{
    "@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
            }
        }
    }]
}

§ 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": {
        "locale": {
          "type": "string"
        },
        "descriptor_map": {
          "type": "array",
          "items": { "$ref": "#/definitions/descriptor" }
        }
      },
      "required": ["descriptor_map"],
      "additionalProperties": false
    }
  },
  "definitions": {
    "descriptor": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "path": { "type": "string" }
      },
      "required": ["id", "path"],
      "additionalProperties": false
    }
  },
  "required": ["presentation_submission"],
  "additionalProperties": false
}

§ 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

§ Appendix

§ Developer Resources

§ JSONPath

§ JSON Schema

Table of Contents