This specification describes an extension mechanism for the Verifiable Credential Data Model, that can be used to represent a Verifiable Credential through a visual, auditory, or haptic medium. It covers rendering a Verifiable Credential to a physical document, digital image, screen reader, or braille output.

This is an experimental specification and is undergoing regular revisions. It is not fit for production deployment.

Introduction

Rendering methods can be used when the [=issuer=] has a specific way that they want to express a [=verifiable credential=] to an observer through a visual, auditory, or haptic mechanism. For example, an [=issuer=] of an employee badge credential might want to include rich imagery of their corporate logo and specific placement of employee information in specific areas of the badge. They might also want to provide an audio read out of the important aspects of the badge for individuals that have accessibility needs related to their eyesight.

Terminology

A conforming render method is any concrete expression of the data model that complies with the normative statements in this specification. Specifically, all relevant normative statements in Sections and of this document MUST be enforced.

A conforming processor is any algorithm realized as software and/or hardware that generates or consumes a [=conforming render method=]. Conforming processors MUST produce errors when non-conforming documents are consumed.

This document also contains examples that contain JSON and JSON-LD content. Some of these examples contain characters that are invalid JSON, such as inline comments (`//`) and the use of ellipsis (`...`) to denote information that adds little value to the example. Implementers are cautioned to remove this content if they desire to use the information as valid JSON or JSON-LD.

Data Model

The following sections outline the data model that is used by this specification for rendering methods

The `renderMethod` Property

The `renderMethod` property is a reserved extension point in the Verifiable Credentials Data Model specification [[VC-DATA-MODEL-2.0]]. An [=issuer=] can utilize this property in a [=verifiable credential=] to express one or more preferred render methods.

renderMethod
The value of the `renderMethod` property MUST specify one or more rendering methods that can be used by software to express the [=verifiable credential=] using a visual, auditory, or haptic mechanism. Each `renderMethod` value MUST specify its `type`, for example, `TemplateRenderMethod`. The precise contents of each rendering hint is determined by the specific `renderMethod` `type` definition.

TemplateRenderMethod

When an [=issuer=] desires to specify template-based rendering instructions for a [=verifiable credential=], they MAY add a `renderMethod` property that uses the data model described below.

Property Description
id An OPTIONAL [=string=] that follows the [[[URL]]] and, when fetched, dereferences to a render template.
type A REQUIRED [=string=] that MUST be the value `TemplateRenderMethod`.
renderSuite A REQUIRED [=string=] that identifies the algorithms that are used for generating the concrete rendering.
name An OPTIONAL human-readable [=string=] that can be displayed to provide a hint to the type of rendering that will be performed. This property might be used in a graphical interface that enables an individual to select between multiple presentation modes.
description An OPTIONAL human-readable [=string=] that provides a more involved description than `name` of when the particular rendering might be useful.
renderProperty An OPTIONAL [=list=] of [=string=] values that each conform to the [[[RFC6901]]] syntax that specifies which properties from the [=verifiable credential=] are exposed when using this specific render method. If `renderProperty` is not provided, the entire [=verifiable credential=] is presumed to be shared when the render method is used.
template An OPTIONAL [=URL=] or [=ordered map|map=] that provides or refers to the template that will be used to perform the rendering. If the value is a [=URL=], it MAY be a `data:` URL [[RFC2397]] containing the template code. If the value is a [=ordered map|map=], it MUST conform to the following rules:
Property Description
id An REQUIRED [=string=] that follows the [[[URL]]] and, when fetched, dereferences to a template such as an SVG or PDF file.
mediaType A RECOMMENDED [=string=] that identifies the media type for the `id` value as specified in [[[RFC6838]]].
digestMultibase An OPTIONAL multibase-encoded Multihash of the template file. The multibase value MUST be `u` (base64url-nopad) and the multihash value MUST be SHA-2 with 256-bits of output (`0x12`).
digestMultibase An OPTIONAL multibase-encoded Multihash of the render method referenced if `id` is specified. The multibase value MUST be `u` (base64url-nopad) and the multihash value MUST be SHA-2 with 256-bits of output (`0x12`).

The data model shown above is expressed in a [=verifiable credential=] in the example below.

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2",
    "https://w3id.org/vc/render-method/v1"
  ],
  "id": "http://example.edu/credentials/3732",
  "type": ["VerifiableCredential", "UniversityDegreeCredential"],
  "issuer": "https://example.edu/issuers/14",
  "validFrom": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "degree": {
      "type": "BachelorDegree",
      "name": "Bachelor of Science and Arts"
    }
  },
  "renderMethod": {
    "type": "TemplateRenderMethod",
    "renderSuite": "svg-mustache",
    "template": {
      "id": "https://example.edu/credential-templates/BachelorDegree",
      "mediaType": "image/svg+xml",
      "digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR",
      "renderProperty": [
        "/issuer", "/validFrom", "/credentialSubject/degree/name"
      ]
    }
  }
  
}
        

In the example above, the [=issuer=] has provided a Mustache-based SVG rendering template for a Bachelor's degree that will be filled in with specific information from the [=verifiable credential=] listed in `renderProperty`.

The `svg-mustache` Render Suite

The `svg-mustache` render suite uses the Mustache templating language to modify an SVG file, which is then used to render a visual representation of the [=verifiable credential=].

In the example below, a fully embedded SVG file is used as the rendering template.

{
  ...
  "renderMethod": {
    "type": "TemplateRenderMethod",
    "renderSuite": "svg-mustache",
    // the SVG file is embedded in the VC
    "template": "data:image/svg+xml;base64,Qjei89...3jZpW"
  }
}
          

The next example links to the SVG file on the Web and secures it against modification by using the `digestMultibase` property.

{
...
"renderMethod": {
  "type": "TemplateRenderMethod",
  "renderSuite": "svg-mustache",
  "template": {
    // this SVG file is fetched from the Web
    "id": "https://degree.example/credential-templates/bachelors",
    "mediaType": "image/svg+xml",
    "digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
  }
}
          

The next example links to the rendering template on the Web and secures it using the `digestMultibase` property:

{
...
"renderMethod": {
  // this render method is fetched from the Web
  "id": "https://degrees.example/bachelors-svg.jsonld",
  "mediaType": "application/ld+json",
  "type": "TemplateRenderMethod",
  "renderSuite": "svg-mustache",
  "digestMultibase": "zQmG270iEu5h6JqWAPdhyxz2dRerWC85Wg6wFl9znFCwYxAp"
}
          

The `pdf-mustache` Render Suite

The `pdf-mustache` render suite uses the Mustache templating language to modify a PDF file, which is then used to render a visual representation of the [=verifiable credential=].

In the example below, a fully embedded PDF file is used as the rendering template.

{
  ...
  "renderMethod": {
    "type": "TemplateRenderMethod",
    "renderSuite": "pdf-mustache",
    // this PDF file is embedded in the VC
    "template": "data:application/pdf;base64,k309SK...pwK83b"
  }
}
          

The next example links to the PDF file on the Web and secures it against modification by using the `digestMultibase` property.

{
...
"renderMethod": {
  "type": "TemplateRenderMethod",
  "renderSuite": "pdf-mustache",
  "template": {
    // this PDF file is fetched from the Web
    "id": "https://degree.example/bachelors.pdf",
    "mediaType": "application/pdf",
    "digestMultibase": "zQmznFCwYxApG270iEu5h6JqWAPdhyxz2dRerWC85Wg6wFl9"
  }
}
          

The next example links to the rendering template on the Web and secures it using the `digestMultibase` property:

{
...
"renderMethod": {
  // this render method is fetched from the Web
  "id": "https://degrees.example/bachelors-pdf.jsonld",
  "type": "TemplateRenderMethod",
  "renderSuite": "pdf-mustache",
  "digestMultibase": "zQmEu5h6JqWAPdhyxmz2dRerWC85Wg6wFl9znFCwYxApG270"
}
          

The `nfc` Render Suite

The `nfc` render suite transmits a binary payload representing the [=verifiable credential=] over a wireless NFC connection.

In the example below, a fully embedded NFC payload is used as the rendering template, which only discloses the barcode identifier associated with the credential.

{
  ...
  "renderMethod": {
    "type": "TemplateRenderMethod",
    "renderSuite": "nfc",
    "name": "Tap to send",
    // the NFC payload is embedded
    "template": "data:application/octet-stream;base64,2QZkpQGDG...G8XJWnROcY4Biw",
    // only the barcode is transmitted over NFC
    "renderProperty": ["/credentialSubject/barcode"]
  }
  
}
        

The `html` Render Suite

The `html` render suite allows template authors to provide an HTML template to render a [=verifiable credential=]. The HTML can be referenced remotely or via a `data:` URL as the value of either `template` or `template.id` (when the value of `template` is an object). JavaScript within the HTML fragment is responsible for rendering the filtered [=verifiable credential=] data provided via an HTML data block (i.e. `<script type="application/vc"></script>`) hosted in a sandboxed iframe alongside the HTML template.

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "type": [
    "VerifiableCredential",
    "NameCredential"
  ],
  "issuer": {
    "id": "did:example:1234",
    "name": "The Issuer"
  },
  "credentialSubject": {
    "name": "Example Name",
    "notRendered": "should not appear"
  },
  "renderMethod": {
    "type": "TemplateRenderMethod",
    "renderSuite": "html",
    "renderProperty": [
      "/issuer/name",
      "/credentialSubject/name"
    ],
    "template": {
      "id": "https://test.example/credential-templates/NameCredential.html",
      "mediaType": "text/html",
      "digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
    },
    "outputPreference": {
      "mode": [
        "visual"
      ],
      "mediaType": "application/html",
      "style": {
        "width": "800px",
        "height": "800px"
      }
    }
  }
}
        

Implementations MUST provide an environment that allows for JavaScript to safely render the HTML template using the filtered [=verifiable credential=] data. The following terminology is used to describe this environment:

host page
Provides the secure environment for rendering the HTML template.
template code
The HTML fragment provided within or remotely referenced by the Render Method.
wrapper code
Code that wraps the HTML template to provide additional security restrictions and communication with the [=host page=].

At minimum, the environment MUST prevent navigation, loading of external content, and access to the [=host page=] in order to prevent tracking and other privacy harms.

Browser based implementations, for example, can provide such an environment using a combination of Content Security Policy [[CSP3]] restrictions on a [=host page=], sandboxing of an `iframe` hosting the HTML template, and wrapper code that wraps the HTML template to add additional CSP restrictions and provides ready and error event communication with the [=host page=].

graph TD
    subgraph Wallet's VC Rendering HTML
        direction LR
        A(VC) -- selectively disclosed --> B{VC subset datablock}
        subgraph "iframe[srcdoc] wrapper code"
            B{VC subset datablock}
            C[HTML/CSS/JS template from renderMethod]
        end
        C[HTML/CSS/JS template from renderMethod] --> D[renderMethodReady]
    end
          
Communication between the [=host page=] and the iframe + [=wrapper code=]
Host Page

The [=host page=] (typically a Wallet or [=verifiable credential=] renderer) MUST prevent the HTML template from navigating the top-level browsing context, accessing external content, accessing the [=host page=], and loading any remote content.

If a [=host page=] is used, the following rules apply:

  • The Content Security Policy (CSP) restrictions MUST include `frame-src 'none'`. This forces the use of `srcdoc` instead of `src` for iframes, which prevents the browser from loading the HTML template. In turn, this forces the [=host page=] code to preload remotely referenced template code and check the response against the related `digestMultibase` value prior to injecting the template into the [=wrapper code=].
  • `sandbox="allow-scripts"` MUST be set on the `iframe` hosting the HTML template to prevent navigation and top-level access.

Template Code

The HTML [=template code=] referenced by the `template` property in the `renderMethod` MUST be an HTML fragment that contains the HTML, CSS, and JavaScript necessary to render the [=verifiable credential=]. The [=template code=] MUST NOT include any `<html>`, `<head>`, or `<body>` tags, as these will be provided by the [=wrapper code=].

Wrapper Code

The template HTML fragment MUST be wrapped in [=wrapper code=] that provides the data block containing the partial [=verifiable credential=] and adds an additional CSP policies to prevent navigation and external content loading. Specifically, the [=wrapper code=] MUST add the following CSP restrictions of `default-src data: 'unsafe-inline'` to prevent any network requests from being made by the [=template code=].

To complete the setup, the [=host page=] MUST inject the [=wrapper code=] (once populated with the [=verifiable credential=] and the [=template code=]) into the iframe's `srcdoc` attribute which will run any JavaScript contained in the [=wrapper code=] and [=template code=].

Ready and Error Events

The iframe created in the [=wrapper code=] MUST provide a communication channel to allow the template to notify the [=host page=] when rendering is complete or if there was an error during rendering. This can be accomplished using the `postMessage` API with a `MessageChannel` setup by the [=wrapper code=].

The JavaScript shown below would be added to the above [=host page=] to add an `onload` event to the iframe which sets up the `MessageChannel`. The [=host page=] also creates a `Promise` that resolves when a `ready` message is received from the [=wrapper code=] or rejects when an `error` message is received. The [=wrapper code=] also provides a `window.renderMethodReady` method for use by the template to notify the [=host page=] that rendering is complete or send back an error message.

With this setup, the template JavaScript can call `window.renderMethodReady()` to notify the [=host page=] that rendering is complete or call `window.renderMethodReady(new Error("error message"))` to notify the [=host page=] of an error.

Algorithms

The following sections outline the algorithms that are used by the `html` render suite to safely render the HTML template. Alternative algorithms MAY be used as long as the security and privacy outcomes as well as the output is the same.

Host Page

The [=host page=] MUST create an `iframe` element to host the HTML template. The [=host page=] MUST set the `sandbox` attribute on the `iframe` to `allow-scripts` to prevent navigation and top-level access.

  1. Let `vc` be the [=verifiable credential=] to be rendered.
  2. Let `renderMethod` be the chosen `renderMethod` property in `vc` where `renderMethod.type` is `TemplateRenderMethod` and `renderMethod.renderSuite` is `html`.
  3. If `renderMethod.template` is a [=string=], then let `template` be the value of `renderMethod.template`.
  4. If `renderMethod.template` is a [=map=], then let `template` be the result of fetching the URL in `renderMethod.template.id`.

The [=host page=] MUST filter the [=verifiable credential=] `vc` to only include the properties specified in `renderMethod.renderProperty`, if it is present. If `renderMethod.renderProperty` is not present, the entire [=verifiable credential=] is used.

This filtering MUST be done by applying the `selectJsonLd` algorithm defined in Section 3.4.13 selectJsonLd of the Data Integrity ECDSA Cryptosuites v1.0 specification [[VC-DI-ECDSA]] to the JSON Pointer [[RFC6901]] values present in `renderMethod.renderProperty`.

The [=host page=] MUST create the [=wrapper code=] by embedding the filtered [=verifiable credential=] and the HTML template into the [=wrapper code=] template defined above.

  1. Let `wrapperCode` be an HTML Document with `<meta http-equiv="Content-Security-Policy" content="default-src data: 'unsafe-inline'">` in the `<head>`.
  2. Let `datablock` be an HTML Data Block with a `type` of `application/vc`.
  3. Set the contents of `datablock` to be the filtered [=verifiable credential=] in stringified JSON format.
  4. Insert `datablock` into the `<head>` of `wrapperCode`.
  5. Insert the value of `template` into the `<body>` of `wrapperCode`.

The [=host page=] MUST set the `srcdoc` attribute of the `iframe` to the resulting [=wrapper code=].

  1. Set the `srcdoc` attribute of the `iframe` to the stringified HTML of `wrapperCode`.

The [=host page=] MUST setup a communication channel with the [=wrapper code=] to receive `ready` and `error` messages as described above.

  1. Let `renderPromise` be a new `Promise` that:
    1. On `resolve`, can be used to display the `iframe` to the user.
    2. On `reject`, display the error message to the user.
  2. In the `onload` event of the `iframe`:
    1. Let `channel` be a new `MessageChannel`.
    2. Create and start a new `port1` listener on `channel` that listens for a `ready` message from the code in `template` now injected into the `iframe` via `wrapperCode`.
    3. In the `port1` listener, if a `ready` message is received, resolve `renderPromise`. If an `error` message is received, reject `renderPromise` with the error message.
    4. Use `postMessage` to send `port2` of `channel` to the `iframe` content window.

The [=host page=] SHOULD use the `renderPromise` to determine when rendering is complete or if there was an error during rendering.

Wrapper Code

The [=wrapper code=] MUST setup to receive communication from the [=host page=] via the `MessageChannel` and provide the `window.renderMethodReady` method for use by the [=template code=].

  1. In the `window.onload` event...
    1. Let `port` be the `MessagePort` received from the [=host page=] via the `message` event.
    2. Create `window.renderMethodReady` function that...
      1. If called with no arguments, sends a `ready` message to the [=host page=] via `port`.
      2. If called with an `Error` argument, sends an `error` message to the [=host page=] via `port` with the error message.

OpenAttestationEmbeddedRenderer

OpenAttestationEmbeddedRenderer is used by an issuer to render a verifiable credential. The verifiable credential is rendered in HTML within an embedded `<iframe>` through a Template Renderer website referenced in the document. This arrangement allows for interactive selective disclosure using OpenAttestationMerkleProofSignature2018.

The Template Renderer is a web application embedded in an iframe. It renders verifiable credentials based on selected templates and must listen for specific messages from the Host application to facilitate the rendering process.

There currently exists a number of OpenAttestationEmbeddedRenderer issuers and decentralized renderer implementations.

When an [=issuer=] desires to specify an embedded rendering instructions for a [=verifiable credential=], they MAY add a `renderMethod` property that uses the data model described below.

Property Description
id A URL that locates a website that implements the OpenAttestationEmbeddedRenderer Action API.
type The `type` property MUST be `OpenAttestationEmbeddedRenderer`.
renderName Name of the template used by the website specified by `id` to render the document. A different template can be used for the decentralized renderer to present a different HTML view of the verifiable credential.

The data model shown above is expressed in a [=verifiable credential=] in the example below.

    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json"
      ],
      "type": ["VerifiableCredential", "OpenAttestationCredential"],
      "validFrom": "2021-03-08T12:00:00+08:00",
      "name": "Republic of Singapore Driving Licence",
      "issuer": {
        "id": "did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90",
        "type": "OpenAttestationIssuer",
        "name": "Government Technology Agency of Singapore (GovTech)",
        "identityProof": { "identityProofType": "DNS-DID", "identifier": "example.openattestation.com" }
      },
      "credentialSubject": {
        "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42",
        "type": ["DriversLicense"],
        "name": "John Doe",
        "address": "123 Choa Chu Kang Road, Singapore 123456",
        "licenses": [
          {
            "class": "3",
            "description": "Motor cars with unladen weight <= 3000kg",
            "effectiveDate": "2013-05-16T00:00:00+08:00"
          },
          {
            "class": "3A",
            "description": "Motor cars with unladen weight <= 3000kg",
            "effectiveDate": "2013-05-16T00:00:00+08:00"
          }
        ]
      },
      "renderMethod": [{
        "id": "https://demo-renderer.opencerts.io",
        "type": "OpenAttestationEmbeddedRenderer",
        "rendererName": "GOVTECH_DEMO"
      }]
    }
      

The [=verifiable credential=] specifies a decentralized renderer at `https://demo-renderer.opencerts.io`, using the template named `GOVTECH_DEMO`.

The decentralized renderer can support different templates that can provide different views of the verifiable credentials. Below are two renderings of the same [=verifiable credential=] using different templates.

Certificate Template
Certificate Template
Transcript Template
Transcript Template
Action API

The Host is the application that displays the document with the help of the Template Renderer. The Template Renderer MUST be a web application embedded within an iframe specified by `renderMethod`.`id`. It MUST communicate with the Host application using postMessage API to perform actions.

All actions follow the same structure. They are composed of `type` and `payload`:

  1. `type` indicates the kind of action being executed, for instance, `RENDER_DOCUMENT` means rendering a document. The type of an action is mandatory.
  2. `payload` indicates optional data associated to the type, for instance, the content of the document to render.

An open source reference implementation is available on GitHub.

The interaction between the Host and the Template Renderer is illustrated in the following diagram.

Sequence Diagram
Sequence Diagram
Host-to-Frame Actions

When the iframe is first displayed, the host sends commands to the iframe to render the document. The 4 types of actions supported are described below.

type payload action
`GET_TEMPLATES`
{ type: "GET_TEMPLATES" }
Obtain a list of templates supported by the renderer for the given document. The list of templates is returned from UPDATE_TEMPLATES call from the iframe.
`SELECT_TEMPLATE`
      {
        type: "SELECT_TEMPLATE",
        payload: "CUSTOM_TEMPLATE"
      }
                  
Select the template to be used for rendering. It should be from the list returned by GET_TEMPLATES. If not found, a default template is used.
`RENDER_DOCUMENT`
      {
        type: "RENDER_DOCUMENT",
        payload: {
          document: {
            credentialSubject: ...,
            renderMethod: ...
          }
        }
      }
                  
Render the verifiable credential inside the IFRAME using the selected template. Document is JSON object form of the verifiable credential.
`PRINT`
{ type: "PRINT" }
MUST show the print dialog so the contents of the IFRAME can be printed.
Frame-to-Host Actions

These are used by the iframe to update the host to make adjustments on formatting, or selective redaction.

type payload action
`OBFUSCATE`
      {
        type: "OBFUSCATE",
        payload: "a[0].b.c",
      }
                
This is used for selective redaction. The Host is informed of the path of the field that has been obfuscated so that the host can create an updated version of the document with the selected field obfuscated.
`UPDATE_HEIGHT`
      {
        type: "UPDATE_HEIGHT",
        payload: 150,
      }
                  
Notify the Host of the height of the embedded iframe in pixels so the Host can adjust the size on the browser.
`UPDATE_TEMPLATES`
      {
        type: "UPDATE_TEMPLATES",
        payload: [
          {
            id: "template1",
            label: "template1",
          },
          {
            id: "template2",
            label: "template2",
          }
        ]
      }
                  
Notify the Host of the list of template names that are usable from RENDER_METHOD, or GET_TEMPLATES calls.

Algorithms

The following sections outline the algorithms that is used by this specification for rendering methods.

Render (TemplateRenderMethod)

The following algorithm is used to transform the SVG image template into the final SVG image that is displayed. The inputs to the algorithm are the [=verifiable credential=] (`verifiableCredential`) and the SVG image source code (`svgImage`). The output is a SVG image.

  1. Generate a map, `replacementMap`, by finding all strings in `svgImage` that start with `{{` (double open braces) and end with `}}` (double close braces). For each string, `templateKey`, that is found:
    1. Generate another string, `templateValue`, by evaluating the value of `templateKey` (without the opening or closing braces) using the JSON Pointer [[RFC6901]] algorithm with the `verifiableCredential` as input to the algorithm. If the evaluation is `null`, set `templateValue` to the empty string.
    2. Set a key in `replacementMap` by using `templateKey` and associate it with `templateValue`.
  2. For every key in `replacementMap`, replace each corresponding string in `svgImage` that matches the key with the associated value in the `replacementMap`.

Security Considerations

The list of security considerations listed below need to be converted into sections:

Privacy Considerations

The list of privacy considerations listed below need to be converted into sections:

Internationalization Considerations

The list of internationalization considerations listed below need to be converted into sections: