@cef-ebsi/verifiable-presentation
TypeScript icon, indicating that this package has built-in type declarations

6.2.1 • Public • Published

EBSI Logo

Verifiable Presentation Library

Create and verify EBSI-compliant W3C Verifiable Presentations in JWT format.

This library extends the @transmute/json-web-signature and @transmute/vc.js libraries by applying additional validation rules. For more details, see VC Framework.

Notes:

Table of Contents

  1. Installation
  2. Usage
  3. Axios config defaults
  4. License

Installation

Using npm:

npm i --save @cef-ebsi/verifiable-presentation

Using yarn:

yarn add @cef-ebsi/verifiable-presentation

Usage

Creating VP JWTs

Prerequisites

Create an EbsiIssuer object to sign VP JWTs:

import type { EbsiIssuer } from "@cef-ebsi/verifiable-presentation";

const signer = {
  did: "did:ebsi:zxaYaUtb8pvoAtYNWbKcveg",
  kid: "did:ebsi:zxaYaUtb8pvoAtYNWbKcveg#CHxYzOqt38Sx6YBfPYhiEdgcwzWk9ty7k0LBa6h70nc",
  publicKeyJwk: {
    kty: "EC",
    crv: "secp256k1",
    x: "YsWJUlskYA_wdyKG8z1LYFICL-KNO7fE3WO5-z7dFa4",
    y: "uo7ddu68ZY7YBreYNY0GQm-bgz6Xf3zXba0Bk0MgMWI",
  },
  privateKeyJwk: {
    kty: "EC",
    crv: "secp256k1",
    x: "YsWJUlskYA_wdyKG8z1LYFICL-KNO7fE3WO5-z7dFa4",
    y: "uo7ddu68ZY7YBreYNY0GQm-bgz6Xf3zXba0Bk0MgMWI",
    d: "<ECC private key>",
  },
  alg: "ES256K",
} satisfies EbsiIssuer;

In order to create a valid VP JWT, the signer MUST either be a Legal Entity (LE) registered in the DID Registry (EBSI DID method v1), or a Natural Person using the did:key method (with the codec jwk_jcs-pub).

Creating a Verifiable Presentation

Specify a payload matching the EbsiVerifiablePresentation interface. Create a JWT by signing it with the previously configured issuer and a target audience using the createVerifiablePresentationJwt function:

import {
  createVerifiablePresentationJwt,
  type EbsiVerifiablePresentation,
  type CreateVerifiablePresentationJwtOptions,
} from "@cef-ebsi/verifiable-presentation";

const vpPayload = {
  id: "urn:did:123456",
  "@context": ["https://www.w3.org/2018/credentials/v1"],
  type: ["VerifiablePresentation"],
  holder:
    "did:key:zBhBLmYmyihtomRdJJNEKzbPj51o4a3GYFeZoRHSABKUwqdjiQPY2cq3LTGRq36RhoZRqix1eq4uA433QJayHdTi8sxm8qdbAbnTyg9dsXCjD8NN7Etcr4f55mRhn9T1d3d6Ec6HgtpcUfemb4ZVKSCDaBrBydsrKAB3TKWNXAkgnz1hseeqf8Y",
  verifiableCredential: [
    "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QiLCJraWQiOiJkaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZyNDSHhZek9xdDM4U3g2WUJmUFloaUVkZ2N3eldrOXR5N2swTEJhNmg3MG5jIn0.eyJqdGkiOiJ1cm46dXVpZDowMDNhMWRkOC1hNWQyLTQyZWYtODE4Mi1lOTIxYzBhOWYyY2QiLCJzdWIiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSIsImlzcyI6ImRpZDplYnNpOnp4YVlhVXRiOHB2b0F0WU5XYktjdmVnIiwibmJmIjoxNjM1NzI0ODAwLCJleHAiOjE5NTM3NjMyMDAsImlhdCI6MTU5MjgzNTEwNCwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiaWQiOiJ1cm46dXVpZDowMDNhMWRkOC1hNWQyLTQyZWYtODE4Mi1lOTIxYzBhOWYyY2QiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVmVyaWZpYWJsZUF0dGVzdGF0aW9uIl0sImlzc3VlciI6ImRpZDplYnNpOnp4YVlhVXRiOHB2b0F0WU5XYktjdmVnIiwiaXNzdWFuY2VEYXRlIjoiMjAyMS0xMS0wMVQwMDowMDowMFoiLCJ2YWxpZEZyb20iOiIyMDIxLTExLTAxVDAwOjAwOjAwWiIsInZhbGlkVW50aWwiOiIyMDUwLTExLTAxVDAwOjAwOjAwWiIsImV4cGlyYXRpb25EYXRlIjoiMjAzMS0xMS0zMFQwMDowMDowMFoiLCJpc3N1ZWQiOiIyMDIwLTA2LTIyVDE0OjExOjQ0WiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkifSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI6Imh0dHBzOi8vYXBpLXBpbG90LmVic2kuZXUvdHJ1c3RlZC1zY2hlbWFzLXJlZ2lzdHJ5L3YzL3NjaGVtYXMvejNNZ1VGVWtiNzIydXE0eDNkdjV5QUptbk5tekRGZUs1VUM4eDgzUW9lTEpNIiwidHlwZSI6IkZ1bGxKc29uU2NoZW1hVmFsaWRhdG9yMjAyMSJ9LCJ0ZXJtc09mVXNlIjp7ImlkIjoiaHR0cHM6Ly9hcGktcGlsb3QuZWJzaS5ldS90cnVzdGVkLWlzc3VlcnMtcmVnaXN0cnkvdjUvaXNzdWVycy9kaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZy9hdHRyaWJ1dGVzL2I0MGZkOWI0MDQ0MThhNDRkMmQ5OTExMzc3YTAzMTMwZGRlNDUwZWI1NDZjNzU1YjViODBhY2Q3ODI5MDJlNmQiLCJ0eXBlIjoiSXNzdWFuY2VDZXJ0aWZpY2F0ZSJ9fX0.fKCREswG43_862Vr8L3lJORgFNzvMZ2hR7p93gfEkhM-qhIIlSlP0AcAgy0c6qu2_2uAIC7mOGnj9AZ3Au2nLw",
  ],
} satisfies EbsiVerifiablePresentation;

const audience = "did:ebsi:zwNAE5xThBpmGJUWAY23kgx";

const vpOptions = {
  // REQUIRED. EBSI URI Authority ([userinfo "@"] host [":" port])
  ebsiAuthority: "api-pilot.ebsi.eu",

  // OPTIONAL. EBSI environment configuration.
  // This option allows you to override the default URLs (TIR, DIDR, TSR).
  ebsiEnvConfig: {
    didRegistry: "https://api-pilot.ebsi.eu/did-registry/v5/identifiers",
    trustedIssuersRegistry:
      "https://api-pilot.ebsi.eu/trusted-issuers-registry/v5/issuers",
    trustedPoliciesRegistry:
      "https://api-pilot.ebsi.eu/trusted-policies-registry/v3/users",
  },

  // OPTIONAL. User-defined VP JWT `nbf`.
  // If none is provided, fallback to `payload.verifiableCredential` JWTs highest `nbf`.
  nbf: 1686048193,

  // OPTIONAL. User-defined VP JWT `exp`.
  // If none is provided, fallback to `payload.verifiableCredential` JWTs lowest `exp`.
  exp: 1686078193,

  // OPTIONAL. The nonce is used to stop a replay attack.
  nonce: "nonce",

  // OPTIONAL. Verification relationship.
  // One of "assertionMethod" | "authentication" | "capabilityDelegation" | "capabilityInvocation"
  // Default: "authentication"
  proofPurpose: "authentication",

  // OPTIONAL. Timeout after which the requests made by the library will fail. Default: 15 seconds
  timeout: 15_000,

  // OPTIONAL. List of trusted hostnames. To be used if the Core Services APIs are hosted on a custom host for instance.
  // If `trustedHostnames` is not defined, the default trusted domains are: "api-test.ebsi.eu", "api-conformance.ebsi.eu", and "api-pilot.ebsi.eu"
  trustedHostnames: ["api.example.net"],

  // OPTIONAL. Determines whether to validate the Verifiable Presentation payload or not.
  // Validation is active by default.
  // Note: even when skipValidation is set to true, the payload must be a valid EBSI Verifiable Presentation.
  skipValidation: false,

  // OPTIONAL. Determines whether to validate the accreditations of the VC issuer or not.
  // Validation is active by default.
  skipAccreditationsValidation: false,

  // OPTIONAL. Determines whether to validate the credential status or not.
  // Validation is active by default.
  skipStatusValidation: false,
} satisfies CreateVerifiablePresentationJwtOptions;

const vpJwt = await createVerifiablePresentationJwt(
  vpPayload,
  signer,
  audience,
  vpOptions,
);

console.log(vpJwt);
// eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QiLCJraWQiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSN6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkifQ.eyJqdGkiOiJ1cm46ZGlkOjEyMzQ1NiIsInN1YiI6ImRpZDprZXk6ekJoQkxtWW15aWh0b21SZEpKTkVLemJQajUxbzRhM0dZRmVab1JIU0FCS1V3cWRqaVFQWTJjcTNMVEdScTM2UmhvWlJxaXgxZXE0dUE0MzNRSmF5SGRUaThzeG04cWRiQWJuVHlnOWRzWENqRDhOTjdFdGNyNGY1NW1SaG45VDFkM2Q2RWM2SGd0cGNVZmVtYjRaVktTQ0RhQnJCeWRzcktBQjNUS1dOWEFrZ256MWhzZWVxZjhZIiwiaXNzIjoiZGlkOmtleTp6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkiLCJpYXQiOjE3MDE3ODE5MTUsImF1ZCI6ImRpZDplYnNpOnp3TkFFNXhUaEJwbUdKVVdBWTIza2d4IiwidnAiOnsiaWQiOiJ1cm46ZGlkOjEyMzQ1NiIsIkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJob2xkZXIiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSIsInZlcmlmaWFibGVDcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlV6STFOa3NpTENKMGVYQWlPaUpLVjFRaUxDSnJhV1FpT2lKa2FXUTZaV0p6YVRwNmVHRlpZVlYwWWpod2RtOUJkRmxPVjJKTFkzWmxaeU5EU0hoWmVrOXhkRE00VTNnMldVSm1VRmxvYVVWa1oyTjNlbGRyT1hSNU4yc3dURUpoTm1nM01HNWpJbjAuZXlKcWRHa2lPaUoxY200NmRYVnBaRG93TUROaE1XUmtPQzFoTldReUxUUXlaV1l0T0RFNE1pMWxPVEl4WXpCaE9XWXlZMlFpTENKemRXSWlPaUprYVdRNmEyVjVPbnBDYUVKTWJWbHRlV2xvZEc5dFVtUktTazVGUzNwaVVHbzFNVzgwWVROSFdVWmxXbTlTU0ZOQlFrdFZkM0ZrYW1sUlVGa3lZM0V6VEZSSFVuRXpObEpvYjFwU2NXbDRNV1Z4TkhWQk5ETXpVVXBoZVVoa1ZHazRjM2h0T0hGa1lrRmlibFI1Wnpsa2MxaERha1E0VGs0M1JYUmpjalJtTlRWdFVtaHVPVlF4WkROa05rVmpOa2huZEhCalZXWmxiV0kwV2xaTFUwTkVZVUp5UW5sa2MzSkxRVUl6VkV0WFRsaEJhMmR1ZWpGb2MyVmxjV1k0V1NJc0ltbHpjeUk2SW1ScFpEcGxZbk5wT25wNFlWbGhWWFJpT0hCMmIwRjBXVTVYWWt0amRtVm5JaXdpYm1KbUlqb3hOak0xTnpJME9EQXdMQ0psZUhBaU9qRTVOVE0zTmpNeU1EQXNJbWxoZENJNk1UVTVNamd6TlRFd05Dd2lkbU1pT25zaVFHTnZiblJsZUhRaU9sc2lhSFIwY0hNNkx5OTNkM2N1ZHpNdWIzSm5Mekl3TVRndlkzSmxaR1Z1ZEdsaGJITXZkakVpWFN3aWFXUWlPaUoxY200NmRYVnBaRG93TUROaE1XUmtPQzFoTldReUxUUXlaV1l0T0RFNE1pMWxPVEl4WXpCaE9XWXlZMlFpTENKMGVYQmxJanBiSWxabGNtbG1hV0ZpYkdWRGNtVmtaVzUwYVdGc0lpd2lWbVZ5YVdacFlXSnNaVUYwZEdWemRHRjBhVzl1SWwwc0ltbHpjM1ZsY2lJNkltUnBaRHBsWW5OcE9ucDRZVmxoVlhSaU9IQjJiMEYwV1U1WFlrdGpkbVZuSWl3aWFYTnpkV0Z1WTJWRVlYUmxJam9pTWpBeU1TMHhNUzB3TVZRd01Eb3dNRG93TUZvaUxDSjJZV3hwWkVaeWIyMGlPaUl5TURJeExURXhMVEF4VkRBd09qQXdPakF3V2lJc0luWmhiR2xrVlc1MGFXd2lPaUl5TURVd0xURXhMVEF4VkRBd09qQXdPakF3V2lJc0ltVjRjR2x5WVhScGIyNUVZWFJsSWpvaU1qQXpNUzB4TVMwek1GUXdNRG93TURvd01Gb2lMQ0pwYzNOMVpXUWlPaUl5TURJd0xUQTJMVEl5VkRFME9qRXhPalEwV2lJc0ltTnlaV1JsYm5ScFlXeFRkV0pxWldOMElqcDdJbWxrSWpvaVpHbGtPbXRsZVRwNlFtaENURzFaYlhscGFIUnZiVkprU2twT1JVdDZZbEJxTlRGdk5HRXpSMWxHWlZwdlVraFRRVUpMVlhkeFpHcHBVVkJaTW1OeE0weFVSMUp4TXpaU2FHOWFVbkZwZURGbGNUUjFRVFF6TTFGS1lYbElaRlJwT0hONGJUaHhaR0pCWW01VWVXYzVaSE5ZUTJwRU9FNU9OMFYwWTNJMFpqVTFiVkpvYmpsVU1XUXpaRFpGWXpaSVozUndZMVZtWlcxaU5GcFdTMU5EUkdGQ2NrSjVaSE55UzBGQ00xUkxWMDVZUVd0bmJub3hhSE5sWlhGbU9Ga2lmU3dpWTNKbFpHVnVkR2xoYkZOamFHVnRZU0k2ZXlKcFpDSTZJbWgwZEhCek9pOHZZWEJwTFhCcGJHOTBMbVZpYzJrdVpYVXZkSEoxYzNSbFpDMXpZMmhsYldGekxYSmxaMmx6ZEhKNUwzWXpMM05qYUdWdFlYTXZlak5OWjFWR1ZXdGlOekl5ZFhFMGVETmtkalY1UVVwdGJrNXRla1JHWlVzMVZVTTRlRGd6VVc5bFRFcE5JaXdpZEhsd1pTSTZJa1oxYkd4S2MyOXVVMk5vWlcxaFZtRnNhV1JoZEc5eU1qQXlNU0o5TENKMFpYSnRjMDltVlhObElqcDdJbWxrSWpvaWFIUjBjSE02THk5aGNHa3RjR2xzYjNRdVpXSnphUzVsZFM5MGNuVnpkR1ZrTFdsemMzVmxjbk10Y21WbmFYTjBjbmt2ZGpVdmFYTnpkV1Z5Y3k5a2FXUTZaV0p6YVRwNmVHRlpZVlYwWWpod2RtOUJkRmxPVjJKTFkzWmxaeTloZEhSeWFXSjFkR1Z6TDJJME1HWmtPV0kwTURRME1UaGhORFJrTW1RNU9URXhNemMzWVRBek1UTXdaR1JsTkRVd1pXSTFORFpqTnpVMVlqVmlPREJoWTJRM09ESTVNREpsTm1RaUxDSjBlWEJsSWpvaVNYTnpkV0Z1WTJWRFpYSjBhV1pwWTJGMFpTSjlmWDAuZktDUkVzd0c0M184NjJWcjhMM2xKT1JnRk56dk1aMmhSN3A5M2dmRWtoTS1xaElJbFNsUDBBY0FneTBjNnF1Ml8ydUFJQzdtT0duajlBWjNBdTJuTHciXX0sIm5iZiI6MTYzNTcyNDgwMCwiZXhwIjoxOTUzNzYzMjAwfQ.hp99g7ue2m0e2XAJd0Z707UGSpL2kVNGFFaK7CtzUuk0POMPUJBZ6vCKa4AxseQV6dDYSulZMTkOlMNAFdZnxw

Verifying JWTs

Prerequisites

Pass in a VP JWT to verify and the target audience using the verifyPresentationJwt function:

import {
  verifyPresentationJwt,
  type VerifyPresentationJwtOptions,
} from "@cef-ebsi/verifiable-presentation";

const vpJwt =
  "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QiLCJraWQiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSN6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkifQ.eyJqdGkiOiJ1cm46ZGlkOjEyMzQ1NiIsInN1YiI6ImRpZDprZXk6ekJoQkxtWW15aWh0b21SZEpKTkVLemJQajUxbzRhM0dZRmVab1JIU0FCS1V3cWRqaVFQWTJjcTNMVEdScTM2UmhvWlJxaXgxZXE0dUE0MzNRSmF5SGRUaThzeG04cWRiQWJuVHlnOWRzWENqRDhOTjdFdGNyNGY1NW1SaG45VDFkM2Q2RWM2SGd0cGNVZmVtYjRaVktTQ0RhQnJCeWRzcktBQjNUS1dOWEFrZ256MWhzZWVxZjhZIiwiaXNzIjoiZGlkOmtleTp6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkiLCJpYXQiOjE3MDE3ODE5MTUsImF1ZCI6ImRpZDplYnNpOnp3TkFFNXhUaEJwbUdKVVdBWTIza2d4IiwidnAiOnsiaWQiOiJ1cm46ZGlkOjEyMzQ1NiIsIkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJob2xkZXIiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSIsInZlcmlmaWFibGVDcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlV6STFOa3NpTENKMGVYQWlPaUpLVjFRaUxDSnJhV1FpT2lKa2FXUTZaV0p6YVRwNmVHRlpZVlYwWWpod2RtOUJkRmxPVjJKTFkzWmxaeU5EU0hoWmVrOXhkRE00VTNnMldVSm1VRmxvYVVWa1oyTjNlbGRyT1hSNU4yc3dURUpoTm1nM01HNWpJbjAuZXlKcWRHa2lPaUoxY200NmRYVnBaRG93TUROaE1XUmtPQzFoTldReUxUUXlaV1l0T0RFNE1pMWxPVEl4WXpCaE9XWXlZMlFpTENKemRXSWlPaUprYVdRNmEyVjVPbnBDYUVKTWJWbHRlV2xvZEc5dFVtUktTazVGUzNwaVVHbzFNVzgwWVROSFdVWmxXbTlTU0ZOQlFrdFZkM0ZrYW1sUlVGa3lZM0V6VEZSSFVuRXpObEpvYjFwU2NXbDRNV1Z4TkhWQk5ETXpVVXBoZVVoa1ZHazRjM2h0T0hGa1lrRmlibFI1Wnpsa2MxaERha1E0VGs0M1JYUmpjalJtTlRWdFVtaHVPVlF4WkROa05rVmpOa2huZEhCalZXWmxiV0kwV2xaTFUwTkVZVUp5UW5sa2MzSkxRVUl6VkV0WFRsaEJhMmR1ZWpGb2MyVmxjV1k0V1NJc0ltbHpjeUk2SW1ScFpEcGxZbk5wT25wNFlWbGhWWFJpT0hCMmIwRjBXVTVYWWt0amRtVm5JaXdpYm1KbUlqb3hOak0xTnpJME9EQXdMQ0psZUhBaU9qRTVOVE0zTmpNeU1EQXNJbWxoZENJNk1UVTVNamd6TlRFd05Dd2lkbU1pT25zaVFHTnZiblJsZUhRaU9sc2lhSFIwY0hNNkx5OTNkM2N1ZHpNdWIzSm5Mekl3TVRndlkzSmxaR1Z1ZEdsaGJITXZkakVpWFN3aWFXUWlPaUoxY200NmRYVnBaRG93TUROaE1XUmtPQzFoTldReUxUUXlaV1l0T0RFNE1pMWxPVEl4WXpCaE9XWXlZMlFpTENKMGVYQmxJanBiSWxabGNtbG1hV0ZpYkdWRGNtVmtaVzUwYVdGc0lpd2lWbVZ5YVdacFlXSnNaVUYwZEdWemRHRjBhVzl1SWwwc0ltbHpjM1ZsY2lJNkltUnBaRHBsWW5OcE9ucDRZVmxoVlhSaU9IQjJiMEYwV1U1WFlrdGpkbVZuSWl3aWFYTnpkV0Z1WTJWRVlYUmxJam9pTWpBeU1TMHhNUzB3TVZRd01Eb3dNRG93TUZvaUxDSjJZV3hwWkVaeWIyMGlPaUl5TURJeExURXhMVEF4VkRBd09qQXdPakF3V2lJc0luWmhiR2xrVlc1MGFXd2lPaUl5TURVd0xURXhMVEF4VkRBd09qQXdPakF3V2lJc0ltVjRjR2x5WVhScGIyNUVZWFJsSWpvaU1qQXpNUzB4TVMwek1GUXdNRG93TURvd01Gb2lMQ0pwYzNOMVpXUWlPaUl5TURJd0xUQTJMVEl5VkRFME9qRXhPalEwV2lJc0ltTnlaV1JsYm5ScFlXeFRkV0pxWldOMElqcDdJbWxrSWpvaVpHbGtPbXRsZVRwNlFtaENURzFaYlhscGFIUnZiVkprU2twT1JVdDZZbEJxTlRGdk5HRXpSMWxHWlZwdlVraFRRVUpMVlhkeFpHcHBVVkJaTW1OeE0weFVSMUp4TXpaU2FHOWFVbkZwZURGbGNUUjFRVFF6TTFGS1lYbElaRlJwT0hONGJUaHhaR0pCWW01VWVXYzVaSE5ZUTJwRU9FNU9OMFYwWTNJMFpqVTFiVkpvYmpsVU1XUXpaRFpGWXpaSVozUndZMVZtWlcxaU5GcFdTMU5EUkdGQ2NrSjVaSE55UzBGQ00xUkxWMDVZUVd0bmJub3hhSE5sWlhGbU9Ga2lmU3dpWTNKbFpHVnVkR2xoYkZOamFHVnRZU0k2ZXlKcFpDSTZJbWgwZEhCek9pOHZZWEJwTFhCcGJHOTBMbVZpYzJrdVpYVXZkSEoxYzNSbFpDMXpZMmhsYldGekxYSmxaMmx6ZEhKNUwzWXpMM05qYUdWdFlYTXZlak5OWjFWR1ZXdGlOekl5ZFhFMGVETmtkalY1UVVwdGJrNXRla1JHWlVzMVZVTTRlRGd6VVc5bFRFcE5JaXdpZEhsd1pTSTZJa1oxYkd4S2MyOXVVMk5vWlcxaFZtRnNhV1JoZEc5eU1qQXlNU0o5TENKMFpYSnRjMDltVlhObElqcDdJbWxrSWpvaWFIUjBjSE02THk5aGNHa3RjR2xzYjNRdVpXSnphUzVsZFM5MGNuVnpkR1ZrTFdsemMzVmxjbk10Y21WbmFYTjBjbmt2ZGpVdmFYTnpkV1Z5Y3k5a2FXUTZaV0p6YVRwNmVHRlpZVlYwWWpod2RtOUJkRmxPVjJKTFkzWmxaeTloZEhSeWFXSjFkR1Z6TDJJME1HWmtPV0kwTURRME1UaGhORFJrTW1RNU9URXhNemMzWVRBek1UTXdaR1JsTkRVd1pXSTFORFpqTnpVMVlqVmlPREJoWTJRM09ESTVNREpsTm1RaUxDSjBlWEJsSWpvaVNYTnpkV0Z1WTJWRFpYSjBhV1pwWTJGMFpTSjlmWDAuZktDUkVzd0c0M184NjJWcjhMM2xKT1JnRk56dk1aMmhSN3A5M2dmRWtoTS1xaElJbFNsUDBBY0FneTBjNnF1Ml8ydUFJQzdtT0duajlBWjNBdTJuTHciXX0sIm5iZiI6MTYzNTcyNDgwMCwiZXhwIjoxOTUzNzYzMjAwfQ.hp99g7ue2m0e2XAJd0Z707UGSpL2kVNGFFaK7CtzUuk0POMPUJBZ6vCKa4AxseQV6dDYSulZMTkOlMNAFdZnxw";
const audience = "did:ebsi:zwNAE5xThBpmGJUWAY23kgx";
const options = {
  // REQUIRED. EBSI URI Authority ([userinfo "@"] host [":" port])
  ebsiAuthority: "api-pilot.ebsi.eu",

  // OPTIONAL. EBSI environment configuration.
  // This option allows you to override the default URLs (TIR, DIDR, TSR).
  ebsiEnvConfig: {
    didRegistry: "https://api-pilot.ebsi.eu/did-registry/v5/identifiers",
    trustedIssuersRegistry:
      "https://api-pilot.ebsi.eu/trusted-issuers-registry/v5/issuers",
    trustedPoliciesRegistry:
      "https://api-pilot.ebsi.eu/trusted-policies-registry/v3/users",
  },

  // OPTIONAL. Timeout after which the requests made by the library will fail. Default: 15 seconds
  timeout: 15_000,

  // OPTIONAL. List of trusted hostnames. To be used if the Core Services APIs are hosted on a custom host for instance.
  // If `trustedHostnames` is not defined, the default trusted domains are: "api-test.ebsi.eu", "api-conformance.ebsi.eu", and "api-pilot.ebsi.eu"
  trustedHostnames: ["api.example.net"],

  // OPTIONAL. Unix timestamp. Optional comparison date.
  // For the JWT to be valid, `nbf` ≤ `validAt` ≤ `exp`.
  validAt: 1686048193,

  // OPTIONAL. Determines whether or not to validate the issuer's accreditations when `termsOfUse` is missing. Default: false
  validateAccreditationWithoutTermsOfUse: false,

  // OPTIONAL. Determines whether to validate the accreditations of the VC issuer or not.
  // Validation is active by default.
  skipAccreditationsValidation: false,

  // OPTIONAL. Determines whether to validate the credential status or not.
  // Validation is active by default.
  skipStatusValidation: false,

  // OPTIONAL. Determines whether to validate the signature of the VP JWT or not.
  // Validation is active by default.
  skipSignatureValidation: false,

  // OPTIONAL. Determines whether to validate the resolution of the VP holder DID or not.
  // Validation is active by default.
  skipHolderDidResolutionValidation: false,

  // OPTIONAL. Verification relationship.
  // One of "assertionMethod" | "authentication" | "capabilityDelegation" | "capabilityInvocation"
  // Default: "authentication"
  proofPurpose: "authentication",
} satisfies VerifyPresentationJwtOptions;

const verifiedVp = await verifyPresentationJwt(vpJwt, audience, options);

console.log(verifiedVp);
/*
{
  id: 'urn:did:123456',
  '@context': [ 'https://www.w3.org/2018/credentials/v1' ],
  type: [ 'VerifiablePresentation' ],
  holder: 'did:key:zBhBLmYmyihtomRdJJNEKzbPj51o4a3GYFeZoRHSABKUwqdjiQPY2cq3LTGRq36RhoZRqix1eq4uA433QJayHdTi8sxm8qdbAbnTyg9dsXCjD8NN7Etcr4f55mRhn9T1d3d6Ec6HgtpcUfemb4ZVKSCDaBrBydsrKAB3TKWNXAkgnz1hseeqf8Y',
  verifiableCredential: [
    'eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QiLCJraWQiOiJkaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZyNDSHhZek9xdDM4U3g2WUJmUFloaUVkZ2N3eldrOXR5N2swTEJhNmg3MG5jIn0.eyJqdGkiOiJ1cm46dXVpZDowMDNhMWRkOC1hNWQyLTQyZWYtODE4Mi1lOTIxYzBhOWYyY2QiLCJzdWIiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSIsImlzcyI6ImRpZDplYnNpOnp4YVlhVXRiOHB2b0F0WU5XYktjdmVnIiwibmJmIjoxNjM1NzI0ODAwLCJleHAiOjE5NTM3NjMyMDAsImlhdCI6MTU5MjgzNTEwNCwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiaWQiOiJ1cm46dXVpZDowMDNhMWRkOC1hNWQyLTQyZWYtODE4Mi1lOTIxYzBhOWYyY2QiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVmVyaWZpYWJsZUF0dGVzdGF0aW9uIl0sImlzc3VlciI6ImRpZDplYnNpOnp4YVlhVXRiOHB2b0F0WU5XYktjdmVnIiwiaXNzdWFuY2VEYXRlIjoiMjAyMS0xMS0wMVQwMDowMDowMFoiLCJ2YWxpZEZyb20iOiIyMDIxLTExLTAxVDAwOjAwOjAwWiIsInZhbGlkVW50aWwiOiIyMDUwLTExLTAxVDAwOjAwOjAwWiIsImV4cGlyYXRpb25EYXRlIjoiMjAzMS0xMS0zMFQwMDowMDowMFoiLCJpc3N1ZWQiOiIyMDIwLTA2LTIyVDE0OjExOjQ0WiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkifSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI6Imh0dHBzOi8vYXBpLXBpbG90LmVic2kuZXUvdHJ1c3RlZC1zY2hlbWFzLXJlZ2lzdHJ5L3YzL3NjaGVtYXMvejNNZ1VGVWtiNzIydXE0eDNkdjV5QUptbk5tekRGZUs1VUM4eDgzUW9lTEpNIiwidHlwZSI6IkZ1bGxKc29uU2NoZW1hVmFsaWRhdG9yMjAyMSJ9LCJ0ZXJtc09mVXNlIjp7ImlkIjoiaHR0cHM6Ly9hcGktcGlsb3QuZWJzaS5ldS90cnVzdGVkLWlzc3VlcnMtcmVnaXN0cnkvdjUvaXNzdWVycy9kaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZy9hdHRyaWJ1dGVzL2I0MGZkOWI0MDQ0MThhNDRkMmQ5OTExMzc3YTAzMTMwZGRlNDUwZWI1NDZjNzU1YjViODBhY2Q3ODI5MDJlNmQiLCJ0eXBlIjoiSXNzdWFuY2VDZXJ0aWZpY2F0ZSJ9fX0.fKCREswG43_862Vr8L3lJORgFNzvMZ2hR7p93gfEkhM-qhIIlSlP0AcAgy0c6qu2_2uAIC7mOGnj9AZ3Au2nLw'
  ]
}
*/

Axios config defaults

The library uses the global axios instance to make HTTP requests. If needed, you can specify config defaults. More information on axios configuration can be found here.

For instance, if you want to override the default HTTPS agent with a custom agent using https-proxy-agent, you can do it like so:

import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";

axios.defaults.httpsAgent = new HttpsProxyAgent("http://168.63.76.32:3128");

License

Copyright (c) 2019 European Commission

Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence");

You may not use this work except in compliance with the Licence.

You may obtain a copy of the Licence at:

Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licence for the specific language governing permissions and limitations under the Licence.

Readme

Keywords

none

Package Sidebar

Install

npm i @cef-ebsi/verifiable-presentation

Weekly Downloads

370

Version

6.2.1

License

EUPL-1.2

Unpacked Size

109 kB

Total Files

33

Last publish

Collaborators

  • iamtxena
  • yhuard
  • joticajulian
  • zgorizzo
  • maurolucc