Verifiable Credentials JSON Schema Specification

JSON Schemas for Verifiable Credentials

W3C Working Draft

More details about this document
This version:
https://www.w3.org/TR/2023/WD-vc-json-schema-20230817/
Latest published version:
https://www.w3.org/TR/vc-json-schema/
Latest editor's draft:
https://w3c.github.io/vc-json-schema/
History:
https://www.w3.org/standards/history/vc-json-schema/
Commit history
Editors:
Gabe Cohen (Block)
Orie Steele (Transmute)
Andres Uribe (Block)
Authors:
Gabe Cohen (Block)
Orie Steele (Transmute)
Feedback:
GitHub w3c/vc-json-schema (pull requests, new issue, open issues)
Related Documents
Verifiable Credentials Data Model

Abstract

Among other things, the [VC-DATA-MODEL-2] specifies the models used for Verifiable Credentials, Verifiable Presentations, and explains the relationships between three parties: issuers, holders, and verifiers. Verifiability, extensibility, and semantic interoperability are critical pieces of functionality referenced throughout the [VC-DATA-MODEL-2]. This specification provides a mechanism to make use of a Credential Schema in Verifiable Credential, leveraging the existing Data Schemas concept.

Status of This Document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

Status of This Document

This document is experimental and is undergoing heavy development. It is inadvisable to implement the specification in its current form. An experimental implementation is available.

This document was published by the Verifiable Credentials Working Group as a Working Draft using the Recommendation track.

Publication as a Working Draft does not imply endorsement by W3C and its Members.

This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 12 June 2023 W3C Process Document.

1. Introduction

This section is non-normative.

This specification provides a mechanism for the use of JSON Schemas with Verifiable Credentials. A significant part of the integrity of a Verifiable Credential comes from the ability to structure its contents so that all three parties — issuer, holder, verifier — may have a consistent mechanism of trust in interpreting the data that they are provided with. We introducing a new data model for an object to facilitate backing Credentials with JSON Schemas that we call a Credential Schema.

This specification provides a standardized way of creating Credential Schemas to be used in credentialing systems. Credential Schemas may apply to any portion of a Verifiable Credential. Multiple JSON Schemas may back a single Verifiable Credential, e.g. a schema for the credentialSubject and another for other credential properties.

1.1 Terminology

This section is non-normative.

The following terms are used to describe concepts in this specification.

claim
An assertion made about a subject.
verifiable credential schema
The data model that this specification defines.
json schema
A declarative language that allows you to annotate and validate JSON documents.
credential
A set of one or more claims made by an issuer. The claims in a credential can be about different subjects.
data minimization
The act of limiting the amount of shared data strictly to the minimum necessary to successfully accomplish a task or goal.
decentralized identifier
A portable URL-based identifier, also known as a DID, associated with an entity. These identifiers are most often used in a verifiable credential and are associated with subjects such that a verifiable credential itself can be easily ported from one repository to another without the need to reissue the credential. An example of a DID is did:example:123456abcdef.
decentralized identifier document
Also referred to as a DID document, this is a document that is accessible using a verifiable data registry and contains information related to a specific decentralized identifier, such as the associated repository and public key information.
digital signature
A mathematical scheme for demonstrating the authenticity of a digital message.
entity
A thing with distinct and independent existence, such as a person, organization, or device that performs one or more roles in the ecosystem.
holder
A role an entity might perform by possessing one or more verifiable credentials and generating presentations from them. A holder is usually, but not always, a subject of the verifiable credentials they are holding. Holders store their credentials in credential repositories.
identity
The means for keeping track of entities across contexts. Digital identities enable tracking and customization of entity interactions across digital contexts, typically using identifiers and attributes. Unintended distribution or use of identity information can compromise privacy. Collection and use of such information should follow the principle of data minimization.
issuer
A role an entity can perform by asserting claims about one or more subjects, creating a verifiable credential from these claims, and transmitting the verifiable credential to a holder.
presentation
Data derived from one or more verifiable credentials, issued by one or more issuers, that is shared with a specific verifier.
repository
A program, such as a storage vault or personal verifiable credential wallet, that stores and protects access to holders' verifiable credentials.
selective disclosure
The ability of a holder to make fine-grained decisions about what information to share.
subject
A thing about which claims are made.
user agent
A program, such as a browser or other Web client, that mediates the communication between holders, issuers, and verifiers.
validation
The assurance that a verifiable credential or a verifiable presentation meets the needs of a verifier and other dependent stakeholders. This specification is constrained to verifying verifiable credentials and verifiable presentations regardless of their usage. Validating verifiable credentials or verifiable presentations is outside the scope of this specification.
verifiable credential
A verifiable credential is a tamper-evident credential that has authorship that can be cryptographically verified. Verifiable credentials can be used to build verifiable presentations, which can also be cryptographically verified.
verifiable data registry
A role a system might perform by mediating the creation and verification of identifiers, keys, and other relevant data, such as verifiable credential schemas, revocation registries, issuer public keys, and so on, which might be required to use verifiable credentials. Some configurations might require correlatable identifiers for subjects. Some registries, such as ones for UUIDs and public keys, might just act as namespaces for identifiers.
verifiable presentation
A verifiable presentation is a tamper-evident presentation encoded in such a way that authorship of the data can be trusted after a process of cryptographic verification. Certain types of verifiable presentations might contain data that is synthesized from, but do not contain, the original verifiable credentials (for example, zero-knowledge proofs).
verification
The evaluation of whether a verifiable credential or verifiable presentation is an authentic and timely statement of the issuer or presenter, respectively. This includes checking that: the credential (or presentation) conforms to the specification; the proof method is satisfied; and, if present, the status check succeeds. Verification of a credential does not imply evaluation of the truth of claims encoded in the credential..
verifier
A role an entity performs by receiving one or more verifiable credentials, optionally inside a verifiable presentation for processing. Other specifications might refer to this concept as a relying party.
URL
A Uniform Resource Locator, as defined by [URL]. URLs can be dereferenced such that they result in a resource, such as a document. The rules for dereferencing, or fetching, a URL are defined by the URL scheme. This specification does not use the term URI or IRI because those terms have been deemed to be confusing to Web developers.
schema resolution
The process that takes as its input a URL and returns a credential schema.

1.2 Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, MUST NOT, RECOMMENDED, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

2. Data Model

The following sections outline the data models for this document, of which there are two: JsonSchema for usage of a [JSON-Schema] directly in a credentialSchema property, and JsonSchemaCredential for usage of a [JSON-Schema] represented as a verifiable credential.

Implementers may find use in packaging a JSON Schema as a verifiable credential when they wish to leverage features of the [VC-DATA-MODEL-2], answering questions such as:

2.1 JsonSchema

This term is part of the Verifiable Credentials Vocabulary v2.0.

JsonSchema is used for the validation of W3C Verifiable Credentials using JSON Schema. When dereferencing the id property associated with the JsonSchema type value the result is a valid JSON Schema document according to its specification version.

The specification version of [JSON-Schema] can be any version noted in the section on JSON Schema Specifications.

Property Description
id The constraints on the id property are listed in the Verifiable Credentials Data Model specification [VC-DATA-MODEL-2]. The value MUST be a URL that identifies the schema associated with the verifiable credential.
type The type property MUST be JsonSchema.

An example of utilizing the VC Data Model's credentialSchema is provided below:

Example 1: Example JsonSchema
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": ["VerifiableCredential", "EmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": [
    "VerifiableCredential",
    "EmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRW1haWxDcmVkZW50aWF
sIl0sImlzc3VlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vaXNzdWVycy8xNCIsImlzc3VhbmNlRG
F0ZSI6IjIwMTAtMDEtMDFUMTk6MjM6MjRaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJka
WQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJlbWFpbEFkZHJlc3MiOiJz
dWJqZWN0QGV4YW1wbGUuY29tIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczovL2V
4YW1wbGUuY29tL3NjaGVtYXMvZW1haWwuanNvbiIsInR5cGUiOiJKc29uU2NoZW1hIn19.huY0B
sfQG_OruuFUbjVk-uL5KPvNZcpWtLi-ncsKtrIceUah0EAnSfXUHOGtvyX6bhuDpxb5LvRJPjnn
VAorPxPVLM0FBlIuST28vjHLBH6APv6socccKxZ-8kANOFnz
graph LR 0("VerifiableCredential") 1{{"id"}} 2("https://example.com/credentials/3732") 3(("type")) 4("EmailCredential") 5("issuer") 6("https://example.com/issuers/14") 7("issuanceDate") 8("2010-01-01T19:23:24Z") 9("credentialSubject") 10{{"id"}} 11("did:example:ebfeb1f712ebc6f1c276e12ec21") 12("emailAddress") 13("subject@example.com") 14("credentialSchema") 15{{"id"}} 16("https://example.com/schemas/email.json") 17(("type")) 18("JsonSchema") 0 --- 1 1 --- 2 0 --- 3 3 --- 4 0 --- 5 5 --- 6 0 --- 7 7 --- 8 0 --- 9 9 --- 10 10 --- 11 9 --- 12 12 --- 13 0 --- 14 14 --- 15 15 --- 16 14 --- 17 17 --- 18

Upon dereferencing the value of the id https://example.com/schemas/email.json, a process also be referred to as schema resolution, the following JSON Schema document is returned:

Example 2: Example Email JSON Schema
{
  "$id": "https://example.com/schemas/email.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "EmailCredential",
  "description": "EmailCredential using JsonSchema",
  "type": "object",
  "properties": {
    "credentialSubject": {
      "type": "object",
      "properties": {
        "emailAddress": {
          "type": "string",
          "format": "email"
        }
      },
      "required": [
        "emailAddress"
      ]
    }
  }
}

2.2 JsonSchemaCredential

This term is part of the Verifiable Credentials Vocabulary v2.0.

JsonSchemaCredential is used for the validation of W3C Verifiable Credentials using JSON Schema, where the JSON Schema is contained with a verifiable credential. When dereferencing the id property associated with the JsonSchemaCredential type value the result is a valid verifiable credential. The resulting verifiable credential's credentialSubject property MUST contain a two properties:

The term definition for using the jsonSchema property within the credentialSubject of a verifiable credential is https://www.w3.org/ns/credentials#jsonSchema.

Any version of [JSON-SCHEMA] in the section on JSON Schema Specifications can be used.

Property Description
id The constraints on the id property are listed in the Verifiable Credentials Data Model specification [VC-DATA-MODEL-2]. The value MUST be a URL that identifies the verifiable credential which contains a credential schema.
type The type property MUST be JsonSchemaCredential.
credentialSubject.id The credentialSubject's id property MUST follow the guidance provided for identifiers in the [VC-DATA-MODEL-2] specification.
credentialSubject.type The credentialSubject's type property MUST be JsonSchema.
credentialSubject.jsonSchema The credentialSubject MUST use the jsonSchema property to represent a valid [JSON-SCHEMA].

An example of utilizing the VC Data Model's credentialSchema is provided below:
Example 3: Example JsonSchemaCredential
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3733",
  "type": ["VerifiableCredential", "ExampleEmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/credentials/3734",
    "type": "JsonSchemaCredential"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3733",
  "type": [
    "VerifiableCredential",
    "ExampleEmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/credentials/3734",
    "type": "JsonSchemaCredential"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzMiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRXhhbXBsZUVtYWlsQ3J
lZGVudGlhbCJdLCJpc3N1ZXIiOiJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlcnMvMTQiLCJpc3
N1YW5jZURhdGUiOiIyMDEwLTAxLTAxVDE5OjIzOjI0WiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7I
mlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwiZW1haWxBZGRy
ZXNzIjoic3ViamVjdEBleGFtcGxlLmNvbSJ9LCJjcmVkZW50aWFsU2NoZW1hIjp7ImlkIjoiaHR
0cHM6Ly9leGFtcGxlLmNvbS9jcmVkZW50aWFscy8zNzM0IiwidHlwZSI6Ikpzb25TY2hlbWFDcm
VkZW50aWFsIn19.TerElezUazak2zlGum2WquEDRplWBzY-gGIusxWJg4hsX97Z5HXmcSPjmJpM
G2zRWnNWj7LfDxTGV_oIdW9CVjjffvt6oXngiEzFVHgDuq1GeP-8weynMbxpAtxtS0ni
graph LR 19("VerifiableCredential") 20{{"id"}} 21("https://example.com/credentials/3733") 22(("type")) 23("ExampleEmailCredential") 24("issuer") 25("https://example.com/issuers/14") 26("issuanceDate") 27("2010-01-01T19:23:24Z") 28("credentialSubject") 29{{"id"}} 30("did:example:ebfeb1f712ebc6f1c276e12ec21") 31("emailAddress") 32("subject@example.com") 33("credentialSchema") 34{{"id"}} 35("https://example.com/credentials/3734") 36(("type")) 37("JsonSchemaCredential") 19 --- 20 20 --- 21 19 --- 22 22 --- 23 19 --- 24 24 --- 25 19 --- 26 26 --- 27 19 --- 28 28 --- 29 29 --- 30 28 --- 31 31 --- 32 19 --- 33 33 --- 34 34 --- 35 33 --- 36 36 --- 37

Upon dereferencing the value of the id https://example.com/credentials/3734, a process also be referred to as schema resolution, the following verifiable credential, representing a JSON Schema, is returned:

Example 4: Example Email Credential Schema
{
  "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3734",
  "type": ["VerifiableCredential", "JsonSchemaCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "https://example.com/schemas/email-credential-schema.json",
    "type": "JsonSchema",
    "jsonSchema": {
       "$id": "https://example.com/schemas/email-credential-schema.json",
       "$schema": "https://json-schema.org/draft/2020-12/schema",
       "name": "EmailCredential",
       "description": "EmailCredential using JsonSchemaCredential",
       "type": "object",
       "properties": {
         "credentialSubject": {
           "type": "object",
           "properties": {
             "emailAddress": {
               "type": "string",
               "format": "email"
             }
           },
           "required": ["emailAddress"]
         }
       }
    }
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3734",
  "type": [
    "VerifiableCredential",
    "JsonSchemaCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "https://example.com/schemas/email-credential-schema.json",
    "type": "JsonSchema",
    "jsonSchema": {
      "$id": "https://example.com/schemas/email-credential-schema.json",
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "name": "EmailCredential",
      "description": "EmailCredential using JsonSchemaCredential",
      "type": "object",
      "properties": {
        "credentialSubject": {
          "type": "object",
          "properties": {
            "emailAddress": {
              "type": "string",
              "format": "email"
            }
          },
          "required": [
            "emailAddress"
          ]
        }
      }
    }
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzQiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiSnNvblNjaGVtYUNyZWR
lbnRpYWwiXSwiaXNzdWVyIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9pc3N1ZXJzLzE0IiwiaXNzdW
FuY2VEYXRlIjoiMjAxMC0wMS0wMVQxOToyMzoyNFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZ
CI6Imh0dHBzOi8vZXhhbXBsZS5jb20vc2NoZW1hcy9lbWFpbC1jcmVkZW50aWFsLXNjaGVtYS5q
c29uIiwidHlwZSI6Ikpzb25TY2hlbWEiLCJqc29uU2NoZW1hIjp7IiRpZCI6Imh0dHBzOi8vZXh
hbXBsZS5jb20vc2NoZW1hcy9lbWFpbC1jcmVkZW50aWFsLXNjaGVtYS5qc29uIiwiJHNjaGVtYS
I6Imh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMjAtMTIvc2NoZW1hIiwibmFtZSI6I
kVtYWlsQ3JlZGVudGlhbCIsImRlc2NyaXB0aW9uIjoiRW1haWxDcmVkZW50aWFsIHVzaW5nIEpz
b25TY2hlbWFDcmVkZW50aWFsIiwidHlwZSI6Im9iamVjdCIsInByb3BlcnRpZXMiOnsiY3JlZGV
udGlhbFN1YmplY3QiOnsidHlwZSI6Im9iamVjdCIsInByb3BlcnRpZXMiOnsiZW1haWxBZGRyZX
NzIjp7InR5cGUiOiJzdHJpbmciLCJmb3JtYXQiOiJlbWFpbCJ9fSwicmVxdWlyZWQiOlsiZW1ha
WxBZGRyZXNzIl19fX19fQ.Fj_C93fBfO0xaoOcQEqZ0TYAwwpQ_M6YzVZTYvu5PzjtrI_7E3g0w
SJN2gwRBQfwReB6ybZUe6aekYg1QSHCRZxZ7muZeaPu0b4FaYoZ4Un8051jWTanI2u_U2p4egcB
graph LR 38("VerifiableCredential") 39{{"id"}} 40("https://example.com/credentials/3734") 41(("type")) 42("JsonSchemaCredential") 43("issuer") 44("https://example.com/issuers/14") 45("issuanceDate") 46("2010-01-01T19:23:24Z") 47("credentialSubject") 48{{"id"}} 49("https://example.com/schemas/email-credential-schema.json") 50(("type")) 51("JsonSchema") 52("jsonSchema") 53("$id") 54("https://example.com/schemas/email-credential-schema.json") 55("$schema") 56("https://json-schema.org/draft/2020-12/schema") 57("name") 58("EmailCredential") 59("description") 60("EmailCredential using JsonSchemaCredential") 61(("type")) 62("object") 63("properties") 64("credentialSubject") 65(("type")) 66("object") 67("properties") 68("emailAddress") 69(("type")) 70("string") 71("format") 72("email") 73("required") 74("emailAddress") 38 --- 39 39 --- 40 38 --- 41 41 --- 42 38 --- 43 43 --- 44 38 --- 45 45 --- 46 38 --- 47 47 --- 48 48 --- 49 47 --- 50 50 --- 51 47 --- 52 52 --- 53 53 --- 54 52 --- 55 55 --- 56 52 --- 57 57 --- 58 52 --- 59 59 --- 60 52 --- 61 61 --- 62 52 --- 63 63 --- 64 64 --- 65 65 --- 66 64 --- 67 67 --- 68 68 --- 69 69 --- 70 68 --- 71 71 --- 72 64 --- 73 73 --- 74

Issue 159: Language on nesting of credential schemas when using CredentialSchema2023 enhancementdiscusspre-cr

Add language about JsonSchemaCredential credentials having a credentialSchema property and the risks of nesting.

3. JSON Schema Specifications

The following section describes the allowed specifications for using a [JSON-Schema] with a credential schema.

To promote conformance and enable interoperability, implementers MUST provide support for JSON Schema specifications where, in the following table, the required column's value is yes.

JSON Schema Specification Date of Publication $schema URI Required
[JSON-SCHEMA-2020-12] 10 June 2022 https://json-schema.org/draft/2020-12/schema Yes
[JSON-SCHEMA-2019-09] 19 March 2020 https://json-schema.org/draft/2019-09/schema No
[JSON-SCHEMA-DRAFT-7] 20 September 2018 http://json-schema.org/draft-07/schema# No
Note: A stable JSON Schema specification is coming

A stable JSON Schema specification is in the works. When it's released, we intend to update this table to require the stable version.

3.1 Reserved Keywords

JSON Schema specifications reserve certain keywords that hold specific meanings and functions during the processing of JSON Schemas. It is crucial to avoid using conflicting keys when creating JSON Schemas. The specification document for each version of JSON Schema lists these reserved keywords, which can be found in the table provided above.

In the upcoming sections we list some keywords that possess unique significance and should not be used in conflicting ways.

Furthermore, we identify specific keywords, that are not explicitly defined by JSON Schema, but are emphasized in this specification to support widespread usage.

3.1.1 $id

Across JSON Schema specifications, the $id keyword identifies a schema resource with its canonical [RFC-6596] URI. The $id MUST be present and its value MUST represent a valid URI-reference [RFC-3986].

It is RECOMMENDED that the value of the $id property match the id value in the credentialSchema object of a verifiable credential, and that the value of the $id is a dereferenceable URL [URL].

3.1.2 $schema

Across JSON Schema specifications, the $schema keyword identifies a JSON Schema providing the feature set for a given JSON Schema specification. This property MUST be present in each schema. For example, when constructing a schema for Draft 2020-12 the value of the $schema identifier MUST be https://json-schema.org/draft/2020-12/schema.

3.1.3 name

It is RECOMMENDED that all JSON Schemas include a name property which provides a human-readable name that describes the schema.

3.1.4 description

JSON Schemas MAY choose to include an optional description property which provides a human-readable sentence describing the schema.

3.2 Representations of JSON Schema

The standard representation of [JSON-SCHEMA] uses the [RFC8259] JSON data interchange syntax with .json as the file extension.

Implementers MAY use OpenAPI Specification's [OAS] [YAML] representation of a [JSON-SCHEMA] with .yaml as the file extension.

Note

YAML representations of JSON Schemas can only be used with credential schemas whose type is JsonSchema.

An example [JSON-SCHEMA] using [YAML] is provided below.
---
"$id": https://example.com/schemas/email.json
"$schema": https://json-schema.org/draft/2020-12/schema
name: Email Credential Schema
description: Email Credential JSON Schema using YAML
type: object
properties:
  credentialSubject:
    type: object
    properties:
      emailAddress:
        type: string
        format: email
    required:
    - emailAddress
example: |-
  {
    "$id": "https://example.com/schemas/email.json",
    "$schema": "https://json-schema.org/draft/2019-09/schema",
    "name": "EmailCredential",
    "description": "Email Credential JSON Schema",
    "type": "object",
    "properties": {
      "credentialSubject": {
        "type": "object",
        "properties": {
          "emailAddress": {
            "type": "string",
            "format": "email"
          }
        },
        "required": ["emailAddress"]
      }
    }
  }

4. Processing

This section details how to process Credential Schemas, which is commonly referred to as JSON schema validation.

There are many open source implementations of [JSON-SCHEMA] validators across many common programming languages. The OpenJS Foundation maintains a list of implementations as a part of the JSON Schema official documentation.

A common feature of a JSON Schema validator is the ability to detect the version of a JSON Schema document and select the validator for that specific version of [JSON-SCHEMA]. This is done by switching on the schema's $schema property and picking the corresponding validator. Schemas without a $schema property are not considered valid and MUST NOT be processed. Implementers SHOULD choose validators which possess this capability and are able to limit validation to the JSON Schema specifications supported by this document.

Conformant implementers MUST support JSON Schema specification versions marked as required in the table defined in the JSON Schema specifications section of this document. Implementers MAY support JSON Schema specification versions not marked as required.

4.1 Integrity Validation

Credential Schemas MAY be packaged as verifiable credentials as defined by usage of the JsonSchemaCredential type. The credential containing a credential schema may include a proof, either embedded according to [VC-DATA-INTEGRITY] or packaged as a [VC-JOSE-COSE].

Secured credentials representing credential schemas SHOULD first be validated according to the rules set out in the aforementioned securing specifications before proceeding with additional processing.

Issue 143: Add examples of validating VC-JWT and Linked Data Proof credentials pre-cr

Provide examples for Data Integrity and VC-JOSE-COSE Credential Schemas

Credential Schemas of type JsonSchema MAY be annotated with integrity information by adding the digestSRI property to the credentialSchema value in the Verifiable Credential which contains the schema, using the method specified in Subresource Integrity. Validation of the integrity of the schema MUST be done before evaluation.

An example of such usage is provided below:

Example 6: Example Verifiable Credential JsonSchema with Integrity Information
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3733",
  "type": ["VerifiableCredential", "EmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema",
    "digestSRI": "sha384-dNwyy/Zs/YjPor8aoOgnaCqb+PH24QcNFxbxM1XoBOxdbgnpQcVaGYH8QunXww2U"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3733",
  "type": [
    "VerifiableCredential",
    "EmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema",
    "digestSRI": "sha384-dNwyy/Zs/YjPor8aoOgnaCqb+PH24QcNFxbxM1XoBOxdbgnpQc
VaGYH8QunXww2U"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzMiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRW1haWxDcmVkZW50aWF
sIl0sImlzc3VlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vaXNzdWVycy8xNCIsImlzc3VhbmNlRG
F0ZSI6IjIwMTAtMDEtMDFUMTk6MjM6MjRaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJka
WQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJlbWFpbEFkZHJlc3MiOiJz
dWJqZWN0QGV4YW1wbGUuY29tIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczovL2V
4YW1wbGUuY29tL3NjaGVtYXMvZW1haWwuanNvbiIsInR5cGUiOiJKc29uU2NoZW1hIiwiZGlnZX
N0U1JJIjoic2hhMzg0LWROd3l5L1pzL1lqUG9yOGFvT2duYUNxYitQSDI0UWNORnhieE0xWG9CT
3hkYmducFFjVmFHWUg4UXVuWHd3MlUifX0.JbfPKboRDf7rX7TuHIvqCTjfNtLep7O-WXUlplRR
4VdDABgulnKvsBxpSzHL4PyNDhzVqZwgI6vY56a3xxK9ZqmNETfSAOwRccOHhjHo6GIy9pm78JZ
8pFngl0MV4cja
graph LR 75("VerifiableCredential") 76{{"id"}} 77("https://example.com/credentials/3733") 78(("type")) 79("EmailCredential") 80("issuer") 81("https://example.com/issuers/14") 82("issuanceDate") 83("2010-01-01T19:23:24Z") 84("credentialSubject") 85{{"id"}} 86("did:example:ebfeb1f712ebc6f1c276e12ec21") 87("emailAddress") 88("subject@example.com") 89("credentialSchema") 90{{"id"}} 91("https://example.com/schemas/email.json") 92(("type")) 93("JsonSchema") 94("digestSRI") 95("sha384-dNwyy/Zs/YjPor8aoOgnaCqb+PH24QcNFxbxM1XoBOxdbgnpQcVaGYH8QunXww2U") 75 --- 76 76 --- 77 75 --- 78 78 --- 79 75 --- 80 80 --- 81 75 --- 82 82 --- 83 75 --- 84 84 --- 85 85 --- 86 84 --- 87 87 --- 88 75 --- 89 89 --- 90 90 --- 91 89 --- 92 92 --- 93 89 --- 94 94 --- 95

4.2 Evaluation

Validation of a given credential against a schema is to be performed according to its associated [JSON-SCHEMA] specification. Validation MUST result in one of the following three possible outcomes:

Examples for the Success and Failure possible outcomes are provided below.

4.2.1 Success Result

Example 7: Example Email JSON Schema
{
  "$id": "https://example.com/schemas/email.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "EmailCredential",
  "description": "EmailCredential using JsonSchema",
  "type": "object",
  "properties": {
    "credentialSubject": {
      "type": "object",
      "properties": {
        "emailAddress": {
          "type": "string",
          "format": "email"
        }
      },
      "required": ["emailAddress"]
     }
   }
}

Validation according to the spec [JSON-SCHEMA-2020-12] yields a Success result when applying it to the VC below.

Example 8: Example Verifiable Credential - validations Success
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": ["VerifiableCredential", "EmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": [
    "VerifiableCredential",
    "EmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "subject@example.com"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRW1haWxDcmVkZW50aWF
sIl0sImlzc3VlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vaXNzdWVycy8xNCIsImlzc3VhbmNlRG
F0ZSI6IjIwMTAtMDEtMDFUMTk6MjM6MjRaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJka
WQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJlbWFpbEFkZHJlc3MiOiJz
dWJqZWN0QGV4YW1wbGUuY29tIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczovL2V
4YW1wbGUuY29tL3NjaGVtYXMvZW1haWwuanNvbiIsInR5cGUiOiJKc29uU2NoZW1hIn19.N2gcC
qQiUabKxL_GeUSBNeQVGMPB8IfRR-h_Kkp91PKKQjx0UB9--H6Nx6A_UVJ0rRYFl_9S3Q_UpqWd
EKH_GkLCM6QJlA9p2ajk9RsvXPWBA72Q_lq1OKS8eL-0z5C6
graph LR 96("VerifiableCredential") 97{{"id"}} 98("https://example.com/credentials/3732") 99(("type")) 100("EmailCredential") 101("issuer") 102("https://example.com/issuers/14") 103("issuanceDate") 104("2010-01-01T19:23:24Z") 105("credentialSubject") 106{{"id"}} 107("did:example:ebfeb1f712ebc6f1c276e12ec21") 108("emailAddress") 109("subject@example.com") 110("credentialSchema") 111{{"id"}} 112("https://example.com/schemas/email.json") 113(("type")) 114("JsonSchema") 96 --- 97 97 --- 98 96 --- 99 99 --- 100 96 --- 101 101 --- 102 96 --- 103 103 --- 104 96 --- 105 105 --- 106 106 --- 107 105 --- 108 108 --- 109 96 --- 110 110 --- 111 111 --- 112 110 --- 113 113 --- 114

4.2.2 Failure Result

Validation according to the spec [JSON-SCHEMA-2020-12] yields a Failure result when applying it to the VC below.

Example 9: Example Verifiable Credential - validation Failure
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": ["VerifiableCredential", "EmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "not an email"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": [
    "VerifiableCredential",
    "EmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "not an email"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRW1haWxDcmVkZW50aWF
sIl0sImlzc3VlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vaXNzdWVycy8xNCIsImlzc3VhbmNlRG
F0ZSI6IjIwMTAtMDEtMDFUMTk6MjM6MjRaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJka
WQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJlbWFpbEFkZHJlc3MiOiJu
b3QgYW4gZW1haWwifSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vc2NoZW1hcy9lbWFpbC5qc29uIiwidHlwZSI6Ikpzb25TY2hlbWEifX0.49X1AcMpsdUtHP
IBi1dwsNi9tYe8G_wYfHLgto-a9F254X5dcztWs3hhQaPdIDr9WiSOqn3onu8vOGKPAqYIWFDt8
nD-k0-oU4qurbvBnRYOZKnzHlewYNYcIFIOsmEC
graph LR 115("VerifiableCredential") 116{{"id"}} 117("https://example.com/credentials/3732") 118(("type")) 119("EmailCredential") 120("issuer") 121("https://example.com/issuers/14") 122("issuanceDate") 123("2010-01-01T19:23:24Z") 124("credentialSubject") 125{{"id"}} 126("did:example:ebfeb1f712ebc6f1c276e12ec21") 127("emailAddress") 128("not an email") 129("credentialSchema") 130{{"id"}} 131("https://example.com/schemas/email.json") 132(("type")) 133("JsonSchema") 115 --- 116 116 --- 117 115 --- 118 118 --- 119 115 --- 120 120 --- 121 115 --- 122 122 --- 123 115 --- 124 124 --- 125 125 --- 126 124 --- 127 127 --- 128 115 --- 129 129 --- 130 130 --- 131 129 --- 132 132 --- 133

4.2.3 Indeterminate Result

Assuming that the implementer does not support [JSON-SCHEMA-2019-09], an example of an Indeterminate evaluation is provided below.

Example 10: Example Email JSON Schema using unsupported JSON Schema version
{
  "$id": "https://example.com/schemas/email.json",
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "name": "EmailCredential",
  "description": "EmailCredential using JsonSchema",
  "type": "object",
  "properties": {
    "credentialSubject": {
      "type": "object",
      "properties": {
        "emailAddress": {
          "type": "string",
          "format": "email"
        }
      },
      "required": [
        "emailAddress"
      ]
    }
  }
}

Example 11: Example Verifiable Credential - validation Indeterminate
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": ["VerifiableCredential", "EmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "not an email"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/3732",
  "type": [
    "VerifiableCredential",
    "EmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "not an email"
  },
  "credentialSchema": {
    "id": "https://example.com/schemas/email.json",
    "type": "JsonSchema"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRW1haWxDcmVkZW50aWF
sIl0sImlzc3VlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vaXNzdWVycy8xNCIsImlzc3VhbmNlRG
F0ZSI6IjIwMTAtMDEtMDFUMTk6MjM6MjRaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJka
WQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJlbWFpbEFkZHJlc3MiOiJu
b3QgYW4gZW1haWwifSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vc2NoZW1hcy9lbWFpbC5qc29uIiwidHlwZSI6Ikpzb25TY2hlbWEifX0.XrTw1u0pZWbmLP
jV44blwBCbR328Nsor25qUalzYD5GYh8eMVMN0kNf1_n-VYeWmOIu0jHDkiywHugHhPHV2GROWb
7iOMI9nYDOhpCzlLtwr1s2IuDYHeZfZ7xASt8R5
graph LR 134("VerifiableCredential") 135{{"id"}} 136("https://example.com/credentials/3732") 137(("type")) 138("EmailCredential") 139("issuer") 140("https://example.com/issuers/14") 141("issuanceDate") 142("2010-01-01T19:23:24Z") 143("credentialSubject") 144{{"id"}} 145("did:example:ebfeb1f712ebc6f1c276e12ec21") 146("emailAddress") 147("not an email") 148("credentialSchema") 149{{"id"}} 150("https://example.com/schemas/email.json") 151(("type")) 152("JsonSchema") 134 --- 135 135 --- 136 134 --- 137 137 --- 138 134 --- 139 139 --- 140 134 --- 141 141 --- 142 134 --- 143 143 --- 144 144 --- 145 143 --- 146 146 --- 147 134 --- 148 148 --- 149 149 --- 150 148 --- 151 151 --- 152

5. Implementation Considerations

This section is non-normative.

This section details some issues implementers of the specification may consider.

5.1 Credential Property Validation

This section is non-normative.

Implementers may wish to validate certain properties in a verifiable credential. To do this, credential schemas can be constructed to validate subsets of a credential's data.

One example of such a construction would be to validate the presence of certain top-level properties in a verifiable credential. The following example demonstrates a schema which enforces that a credential issued against it has an validUntil property and includes evidence.

Example 12: ValidUntil and Evidence Credential Schema
{
  "$id": "validuntil-and-evidence-schema",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "Example validUntil and evidence schema",
  "description": "Schema requiring validUntil and evidence properties",
  "type": "object",
  "properties": {
    "validUntil": {
      "type": "object"
    },
    "evidence": {
      "type": "object"
    }
  },
  "required": ["validUntil", "evidence"]
}

5.2 Additional Properties

This section is non-normative.

In using [JSON-Schema] it is advised that implementers avoid setting the additionalProperties to false. Doing so could inadvertently exclude properties in a credential from passing validation.

As an example, consider a credential schema that is intended to validate the credentialSubject property of a credential. It is common for the credentialSubject property to include an id, denoting the identifier the subject. Not including this id property in a given schema would result in validation failure. The simple alternative is to avoid setting additionalProperties to false.

Example 13: Example Name Credential Schema
{
  "$id": "name-schema",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "Name schema",
  "description": "A schema capturing a human name",
  "type": "object",
  "properties": {
    "credentialSubject": {
      "type": "object",
      "properties": {
        "name": {
          "type": "object",
          "properties": {
            "firstName": {
              "type": "string"
            },
            "lastName": {
              "type": "string"
            },
            "additionalProperties": false
          },
          "required": [
            "firstName",
            "lastName"
          ]
        }
      }
    }
  }
}

5.3 Versioning

This section is non-normative.

Versioning is not provided as an explicit feature of this specification. Implementers are advised to make backwards compatabile changes to schemas, should they be adjusted. Otherwise, it is advised that new credential schemas be created with unique identifiers to avoid processing conflicts.

5.4 Content Integrity Protection

This section is non-normative.

It is important to make sure that credential schemas have not been tampered with before processing. When making use of the JsonSchemaCredential2023 representation of a schema, the credential's associated integrity protection mechanism can be used to detect mutations of a credential schema via its digital signature.

As an alternative, the aforementioned [SRI] scheme may be used to provide content integrity protection, ensuring that the underlying credential schema resource has not been tampered with.

5.5 Storage

This section is non-normative.

Credential schemas can be stored on any number of storage media such as a distributed ledger, traditional database, or decentralized file storage. For more robust availability guarantees, the same schema could be replicated across multiple file stores.

5.6 Multiple Schemas

This section is non-normative.

A common use case is to include multiple schemas to validate against a single verifiable Credential. One such use case is to utilize the JSON Schema defined by the [VC-DATA-MODEL-2] in addition to a schema to validate a specific property in the credential, such as the credentialSubject. Multiple schemas MAY be combined using native constructs from the [JSON-SCHEMA] specification, through utilizing properties such as oneOf, anyOf, or allOf.

An example of how to construct such a schema using the [JSON-SCHEMA] property allOf is provided below, combining schemas for a verifiable credential, name, and email address:

Example 14: Multiple Schema Credential Schema Example
{
  "allOf": [
    {
      "$ref": "https://raw.githubusercontent.com/w3c/vc-data-model/main/schema/verifiable-credential/verifiable-credential-schema.json"
    },
    {
      "$id": "name-schema",
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "name": "Name schema",
      "description": "A schema capturing a human name",
      "type": "object",
      "properties": {
        "credentialSubject": {
          "type": "object",
          "properties": {
            "name": {
              "type": "object",
              "properties": {
                "firstName": {
                  "type": "string"
                },
                "lastName": {
                  "type": "string"
                },
                "additionalProperties": false
              },
              "required": [
                "firstName",
                "lastName"
              ]
            }
          }
        }
      }
    },
    {
      "$id": "email-schema-1.0",
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "name": "Email schema",
      "description": "A schema requiring an email address.",
      "type": "object",
      "properties": {
        "credentialSubject": {
          "type": "object",
          "properties": {
            "email": {
              "type": "object",
              "properties": {
                "emailAddress": {
                  "type": "string",
                  "format": "email"
                }
              },
              "required": ["emailAddress"]
            }
          }
        }
      }
    }
  ]
}

The example above is used to validate every property in the following verifiable credential:

Example 15: Multiple Schema Verifiable Credential Example
{
    "@context": ["https://www.w3.org/ns/credentials/v2"],
    "id": "4995c86c-851f-43a6-9dd2-03dc891091fd",
    "type": ["VerifiableCredential"],
    "issuer": "did:example:1234",
    "validFrom": "2023-01-01T05:05:05Z",
    "credentialSubject": {
        "firstName": "Alice",
        "lastName": "Bobertson",
        "emailAddress": "alice@bobertson.com"
    },
    "credentialSchema": {
        "id": "multiple-credential-schema-test",
        "type": "JsonSchemaCredential"
    }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "did:example:1234",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2"
  ],
  "id": "4995c86c-851f-43a6-9dd2-03dc891091fd",
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "did:example:1234",
  "validFrom": "2023-01-01T05:05:05Z",
  "credentialSubject": {
    "firstName": "Alice",
    "lastName": "Bobertson",
    "emailAddress": "alice@bobertson.com"
  },
  "credentialSchema": {
    "id": "multiple-credential-schema-test",
    "type": "JsonSchemaCredential"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6ImRpZDpleGFtcGxlOjEyMzQ
iLCJpYXQiOjE2OTIzMDY0MTd9.eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvbnMvY
3JlZGVudGlhbHMvdjIiXSwiaWQiOiI0OTk1Yzg2Yy04NTFmLTQzYTYtOWRkMi0wM2RjODkxMDkx
ZmQiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sImlzc3VlciI6ImRpZDpleGFtcGx
lOjEyMzQiLCJ2YWxpZEZyb20iOiIyMDIzLTAxLTAxVDA1OjA1OjA1WiIsImNyZWRlbnRpYWxTdW
JqZWN0Ijp7ImZpcnN0TmFtZSI6IkFsaWNlIiwibGFzdE5hbWUiOiJCb2JlcnRzb24iLCJlbWFpb
EFkZHJlc3MiOiJhbGljZUBib2JlcnRzb24uY29tIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQi
OiJtdWx0aXBsZS1jcmVkZW50aWFsLXNjaGVtYS10ZXN0IiwidHlwZSI6Ikpzb25TY2hlbWFDcmV
kZW50aWFsIn19.hItIpCGcTtWdaYHjuYkf1EPQo5uwIUFeXG1ey8iisM7x81KA9gj6j0bf9pCQE
3OCZzv2Jgz1knb0vaK8lKY17RHFBTA49eBIXYVrhB3u3Lg4hIg7QVefbUWf7mnt3l3p
graph LR 153("VerifiableCredential") 154{{"id"}} 155("4995c86c-851f-43a6-9dd2-03dc891091fd") 156("issuer") 157("did:example:1234") 158("validFrom") 159("2023-01-01T05:05:05Z") 160("credentialSubject") 161("firstName") 162("Alice") 163("lastName") 164("Bobertson") 165("emailAddress") 166("alice@bobertson.com") 167("credentialSchema") 168{{"id"}} 169("multiple-credential-schema-test") 170(("type")) 171("JsonSchemaCredential") 153 --- 154 154 --- 155 153 --- 156 156 --- 157 153 --- 158 158 --- 159 153 --- 160 160 --- 161 161 --- 162 160 --- 163 163 --- 164 160 --- 165 165 --- 166 153 --- 167 167 --- 168 168 --- 169 167 --- 170 170 --- 171

Using allOf when composing a JSON Schema can easily result in a schema for which all JSON documents will fail to validate. Such a situation may happen when multiple schemas reference the same property. Implementers are advised to test their schemas against a set of sample input documents before introducing any real world usage. Including sample input that suceeds and fails is considered a good practice.

5.7 Validity of a Verifiable Credential

This section is non-normative.

Validation against a [JSON-SCHEMA] may be confused with validation or verification of a Verifiable Credential. A valid credential according to a [JSON-SCHEMA] refers only to the structure of the claims comprising a Verifiable Credential. This idea of validity does not imply anything about the validity of the Verifiable Credential itself. It's possible for a Verifiable Credential to be considered valid by one verifier, while another verifier would not consider it valid.

5.8 Relationship to Verifiable Credential Type Property

This section is non-normative.

It is common to define a credential schema that will be set for Verifiable Credentials whose type property contains a specific type. In this scenario, it is advised to use the value of the specific type in the id or in a name or description property. of a [JSON-Schema].

The example below illustrates this for EmailCredential:

Example 16: Verifiable Credential with Schema Type
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/email-credential",
  "type": ["VerifiableCredential", "EmailCredential"],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "tester@example.com"
  },
  "credentialSchema": {
    "id": "https://example.org/examples/email.json",
    "type": "JsonSchema"
  }
}
---------------- Decoded Protected Header ----------------
{
  "alg": "ES384",
  "typ": "vc+ld+jwt",
  "iss": "https://example.com/issuers/14",
  "iat": 1692306417
}
---------------- Decoded Protected Claimset ----------------
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "https://example.com/credentials/email-credential",
  "type": [
    "VerifiableCredential",
    "EmailCredential"
  ],
  "issuer": "https://example.com/issuers/14",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "emailAddress": "tester@example.com"
  },
  "credentialSchema": {
    "id": "https://example.org/examples/email.json",
    "type": "JsonSchema"
  }
}
---------------- Compact Encoded JSON Web Token ----------------
eyJhbGciOiJFUzM4NCIsInR5cCI6InZjK2xkK2p3dCIsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5
jb20vaXNzdWVycy8xNCIsImlhdCI6MTY5MjMwNjQxN30.eyJAY29udGV4dCI6WyJodHRwczovL3
d3dy53My5vcmcvbnMvY3JlZGVudGlhbHMvdjIiLCJodHRwczovL3d3dy53My5vcmcvbnMvY3JlZ
GVudGlhbHMvZXhhbXBsZXMvdjIiXSwiaWQiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRp
YWxzL2VtYWlsLWNyZWRlbnRpYWwiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRW1
haWxDcmVkZW50aWFsIl0sImlzc3VlciI6Imh0dHBzOi8vZXhhbXBsZS5jb20vaXNzdWVycy8xNC
IsImlzc3VhbmNlRGF0ZSI6IjIwMTAtMDEtMDFUMTk6MjM6MjRaIiwiY3JlZGVudGlhbFN1YmplY
3QiOnsiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJlbWFp
bEFkZHJlc3MiOiJ0ZXN0ZXJAZXhhbXBsZS5jb20ifSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI
6Imh0dHBzOi8vZXhhbXBsZS5vcmcvZXhhbXBsZXMvZW1haWwuanNvbiIsInR5cGUiOiJKc29uU2
NoZW1hIn19.Z7mfQcRneXC2gxwDfLZsmCJ0-zl6F1GczQPSMJGIOalATVrZoxLNl6vKk38PWr0E
etYdrbfbG8IjvSjY-lgdk_lyzgeyS2xUXIcLzmL0IZPiKRZZXaH9b2XS_uF0POSD
graph LR 172("VerifiableCredential") 173{{"id"}} 174("https://example.com/credentials/email-credential") 175(("type")) 176("EmailCredential") 177("issuer") 178("https://example.com/issuers/14") 179("issuanceDate") 180("2010-01-01T19:23:24Z") 181("credentialSubject") 182{{"id"}} 183("did:example:ebfeb1f712ebc6f1c276e12ec21") 184("emailAddress") 185("tester@example.com") 186("credentialSchema") 187{{"id"}} 188("https://example.org/examples/email.json") 189(("type")) 190("JsonSchema") 172 --- 173 173 --- 174 172 --- 175 175 --- 176 172 --- 177 177 --- 178 172 --- 179 179 --- 180 172 --- 181 181 --- 182 182 --- 183 181 --- 184 184 --- 185 172 --- 186 186 --- 187 187 --- 188 186 --- 189 189 --- 190

Example 17: Schema with Matching Type Name
{
  "$id": "https://example.com/schemas/email.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "Email Credential",
  "description": "Email Credential Schema for usage in JsonSchema",
  "type": "object",
  "properties": {
    "credentialSubject": {
      "type": "object",
      "properties": {
        "emailAddress": {
          "type": "string",
          "format": "email"
        }
      },
      "required": [
        "emailAddress"
      ]
    }
  }
}

It is important to note that a credential schema enables issuers to communicate how to process the structure of data inside a verifiable credential, whereas the type property of a verifiable credential lets issuers communicate the semantics of the data. It is advised to associate all properties that have a semantic mapping with a property in a credential schema.

6. Privacy Considerations

This section is non-normative.

This section details the general privacy considerations and specific privacy implications of deploying this specification into production environments.

6.1 Personally Identifiable Information

This section is non-normative.

Data associated with schemas and verifiable credentials are susceptible to privacy violations when shared. Personally identifying data, such as a government-issued identifier, address, or name, can be used to track and correlate entities. Even less overt personal data such as a birthdate or postal code has the ability to result in correlation and de-anonymization.

Implementers are strongly advised to avoid constructing schemas with any personally identifiable information (PII).

If such personally identifiable information is necessary in a schema, or a credential schema, implementers are strongly advised to use mechanisms while storing and transporting verifiable credentials that protect the data from those who should not access it such as Transportation Layer Security (TLS) or other means of encrypting the data whether in transit or at rest.

6.2 Verifier Caching

This section is non-normative.

Since schemas are immutable, they are highly cachable. It is possible for verifiers to increase the privacy of the holder whose verifiable credential is being checked by caching schemas that have been fetched from remote servers. By caching the content locally, less correlatable information can be inferred from verifier-based access patterns on the schema.

6.3 Content Distribution Networks

This section is non-normative.

The use of content distribution networks by issuers can increase the privacy of holders by reducing or eliminating requests for the schemas lists from the issuer. Often, a request for a schema list will be served by an edge device and thus be faster and reduce the load on the server as well as cloaking verifiers and holders from issuers.

7. Security Considerations

This section is non-normative.

There are a number of security considerations that implementers should be aware of when processing data described by this specification. Ignoring or not understanding the implications of this section can result in security vulnerabilities.

7.1 Issuer Impersonation

This section is non-normative.

It is possible for a schema to become authoritative, such as schemas provided by a recognized industry group like a consoritum of financial companies. To avoid confusion as to the authorship of credential schemas it is advised that they are packaged as secured verifiable credentials.

8. Accessibility Considerations

This section is non-normative.

There are a number of accessibility considerations implementers should be aware of when processing data described in this specification. As with any web standards or protocols implementation, ignoring accessibility issues makes this information unusable to a large subset of the population. It is important to follow accessibility guidelines and standards, such as [WCAG21], to ensure all people, regardless of ability, can make use of this data. This is especially important when establishing systems utilizing cryptography, which have historically created problems for assistive technologies.

JSON Schemas are designed to be a machine-readable format which provides static validation. As such, human readability is a secondary concern. When using a verifiable credential to represent a schema, we recommend following the guidance in the VC Data Model.

9. Internationalization Considerations

This section is non-normative.

There are a number of internationalization considerations implementers should be aware of when publishing data described in this specification. As with any web standards or protocols implementation, ignoring internationalization makes it difficult for data to be produced and consumed across a disparate set of languages and societies, which would limit the applicability of the specification and significantly diminish its value as a standard.

JSON Schemas are JSON text intended primarily for machines to read, since they are used for strict static validation of data. Language and text direction concerns are addressed by the noted specification documents for JSON Schema itself.

When using a verifiable credential to represent a schema, we recommend following the guidance in the VC Data Model.

10. IANA Considerations

10.1 Media Types

10.1.1 JsonSchema

This specification acknowledges the use of the application/schema+json and application/json Media Types specifically for identifying a [JSON-SCHEMA] with usage of the JsonSchema type, as registered in JSON Schema specifications.

When using the JsonSchema type with a YAML representation of a JSON Schema, defined by [OAS], the types application/openapi+yaml or application/yaml may be used.

10.1.2 JsonSchemaCredential

This specification acknowledges the use of the application/vc+ld+json, application/vc+ld+json+jwt, and application/vc+ld+json+sd-jwt Media Types specifically for identifying a [JSON-SCHEMA] with usage of the JsonSchemaCredential type, as registered in the [VC-DATA-MODEL-2], [VC-JOSE-COSE], and [SD-JWT] specifications respectively.

A. References

A.1 Normative references

[JSON-Schema]
JSON Schema: A Media Type for Describing JSON Documents. OpenJS Foundation. URL: https://json-schema.org/specification.html
[JSON-SCHEMA-2019-09]
JSON Schema 2019-09 Release Notes. OpenJS Foundation. URL: https://json-schema.org/draft/2019-09/release-notes.html
[JSON-SCHEMA-2020-12]
JSON Schema 2020-12 Release Notes. OpenJS Foundation. URL: https://json-schema.org/draft/2020-12/release-notes.html
[JSON-SCHEMA-DRAFT-7]
JSON Schema Draft-07 Release Notes. OpenJS Foundation. URL: https://json-schema.org/draft-07/json-schema-release-notes.html
[OAS]
OpenAPI Specification Version 3.1.0. Darrel Miller; Jeremy Whitlock; Marsh Gardiner ; Mike Ralphson; Ron Ratovsky; Uri Sarid. OpenAPI Initiative. URL: https://swagger.io/specification/
[RFC-3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. January 2005. URL: https://www.rfc-editor.org/rfc/rfc3986
[RFC-6596]
The Canonical Link Relation. M. Ohye; J. Kupke. April 2012. URL: https://www.rfc-editor.org/rfc/rfc6596
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8259]
The JavaScript Object Notation (JSON) Data Interchange Format. T. Bray, Ed.. IETF. December 2017. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc8259
[SD-JWT]
Selective Disclosure for JWTs (SD-JWT). Daniel Fett; Kristina Yasuda; Brian Campbell. IETF. Internet-Draft. URL: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-selective-disclosure-jwt-05
[sri]
Subresource Integrity. Devdatta Akhawe; Frederik Braun; Francois Marier; Joel Weinberger. W3C. 23 June 2016. W3C Recommendation. URL: https://www.w3.org/TR/SRI/
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[VC-DATA-INTEGRITY]
Verifiable Credential Data Integrity 1.0. David Longley; Manu Sporny. W3C Verifiable Credentials Working Group. Working Draft. URL: https://www.w3.org/TR/vc-data-integrity/
[vc-data-model]
Verifiable Credentials Data Model v1.1. Manu Sporny; Grant Noble; Dave Longley; Daniel Burnett; Brent Zundel; Kyle Den Hartog. W3C. 3 March 2022. W3C Recommendation. URL: https://www.w3.org/TR/vc-data-model/
[VC-DATA-MODEL-2]
Verifiable Credentials Data Model v2.0. Manu Sporny; Orie Steele; Michael B. Jones; Gabe Cohen; Oliver Terbu. W3C Verifiable Credentials Working Group. Working Draft. URL: https://www.w3.org/TR/vc-data-model-2.0/
[VC-JOSE-COSE]
Securing Verifiable Credentials using JOSE and COSE. Orie Steele; Michael Jones; Michael Prorock. W3C. URL: https://www.w3.org/TR/vc-jose-cose/
[YAML]
YAML Ain’t Markup Language (YAML™) version 1.2. YAML Language Development Team. URL: https://yaml.org/spec/1.2.2/

A.2 Informative references

[WCAG21]
Web Content Accessibility Guidelines (WCAG) 2.1. Andrew Kirkpatrick; Joshue O'Connor; Alastair Campbell; Michael Cooper. W3C. 5 June 2018. W3C Recommendation. URL: https://www.w3.org/TR/WCAG21/