Create and verify EBSI-compliant W3C Verifiable Presentations in JWT format.
This library uses DIF's did-jwt under the hood and applies additional validation rules specific to EBSI. For more details, see VC Framework.
Notes:
- this library implements the VC Data Model 1.1 specification.
- this library only supports
2020-12
JSON Schemas.
Using npm:
npm i --save @cef-ebsi/verifiable-presentation
Using yarn:
yarn add @cef-ebsi/verifiable-presentation
All the methods described below require a configuration object. The library exports a TypeScript interface that you can use to properly define the configuration object. Here's an example of such a configuration object:
import type { EbsiVpEnvConfiguration } from "@cef-ebsi/verifiable-presentation";
const config = {
// List of trusted hosts
hosts: ["api-pilot.ebsi.eu"],
// Defines the URI scheme
scheme: "ebsi",
// Defines the network config
network: {
// Network component, as it appears in the URI
name: "pilot",
// Whether the network component is optional or not
isOptional: false,
},
// The list of the supported services (with their version number)
services: {
"did-registry": "v5",
"trusted-issuers-registry": "v5",
"trusted-policies-registry": "v3",
"trusted-schemas-registry": "v3",
},
} as const satisfies EbsiVpEnvConfiguration;
Create an EbsiIssuer
object to sign VP JWTs:
import type { EbsiIssuer } from "@cef-ebsi/verifiable-presentation";
import { ES256KSigner } from "did-jwt";
const signer = {
did: "did:ebsi:zxaYaUtb8pvoAtYNWbKcveg",
kid: "did:ebsi:zxaYaUtb8pvoAtYNWbKcveg#CHxYzOqt38Sx6YBfPYhiEdgcwzWk9ty7k0LBa6h70nc",
alg: "ES256K",
signer: ES256KSigner(privateKey),
} 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
).
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 options = {
// OPTIONAL. Timeout after which the requests made by the library will fail. Default: 15 seconds
// timeout: 15_000,
// 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,
// OPTIONAL. Determines whether to validate the credential subject or not
// Validation is active by default.
// skipCredentialSubjectValidation: false,
// 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",
} satisfies CreateVerifiablePresentationJwtOptions;
const vpJwt = await createVerifiablePresentationJwt(
vpPayload,
signer,
audience,
config,
options,
);
console.log(vpJwt);
// eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QiLCJraWQiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSN6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkifQ.eyJqdGkiOiJ1cm46ZGlkOjEyMzQ1NiIsInN1YiI6ImRpZDprZXk6ekJoQkxtWW15aWh0b21SZEpKTkVLemJQajUxbzRhM0dZRmVab1JIU0FCS1V3cWRqaVFQWTJjcTNMVEdScTM2UmhvWlJxaXgxZXE0dUE0MzNRSmF5SGRUaThzeG04cWRiQWJuVHlnOWRzWENqRDhOTjdFdGNyNGY1NW1SaG45VDFkM2Q2RWM2SGd0cGNVZmVtYjRaVktTQ0RhQnJCeWRzcktBQjNUS1dOWEFrZ256MWhzZWVxZjhZIiwiaXNzIjoiZGlkOmtleTp6QmhCTG1ZbXlpaHRvbVJkSkpORUt6YlBqNTFvNGEzR1lGZVpvUkhTQUJLVXdxZGppUVBZMmNxM0xUR1JxMzZSaG9aUnFpeDFlcTR1QTQzM1FKYXlIZFRpOHN4bThxZGJBYm5UeWc5ZHNYQ2pEOE5ON0V0Y3I0ZjU1bVJobjlUMWQzZDZFYzZIZ3RwY1VmZW1iNFpWS1NDRGFCckJ5ZHNyS0FCM1RLV05YQWtnbnoxaHNlZXFmOFkiLCJpYXQiOjE3MDE3ODE5MTUsImF1ZCI6ImRpZDplYnNpOnp3TkFFNXhUaEJwbUdKVVdBWTIza2d4IiwidnAiOnsiaWQiOiJ1cm46ZGlkOjEyMzQ1NiIsIkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJob2xkZXIiOiJkaWQ6a2V5OnpCaEJMbVlteWlodG9tUmRKSk5FS3piUGo1MW80YTNHWUZlWm9SSFNBQktVd3FkamlRUFkyY3EzTFRHUnEzNlJob1pScWl4MWVxNHVBNDMzUUpheUhkVGk4c3htOHFkYkFiblR5Zzlkc1hDakQ4Tk43RXRjcjRmNTVtUmhuOVQxZDNkNkVjNkhndHBjVWZlbWI0WlZLU0NEYUJyQnlkc3JLQUIzVEtXTlhBa2duejFoc2VlcWY4WSIsInZlcmlmaWFibGVDcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlV6STFOa3NpTENKMGVYQWlPaUpLVjFRaUxDSnJhV1FpT2lKa2FXUTZaV0p6YVRwNmVHRlpZVlYwWWpod2RtOUJkRmxPVjJKTFkzWmxaeU5EU0hoWmVrOXhkRE00VTNnMldVSm1VRmxvYVVWa1oyTjNlbGRyT1hSNU4yc3dURUpoTm1nM01HNWpJbjAuZXlKcWRHa2lPaUoxY200NmRYVnBaRG93TUROaE1XUmtPQzFoTldReUxUUXlaV1l0T0RFNE1pMWxPVEl4WXpCaE9XWXlZMlFpTENKemRXSWlPaUprYVdRNmEyVjVPbnBDYUVKTWJWbHRlV2xvZEc5dFVtUktTazVGUzNwaVVHbzFNVzgwWVROSFdVWmxXbTlTU0ZOQlFrdFZkM0ZrYW1sUlVGa3lZM0V6VEZSSFVuRXpObEpvYjFwU2NXbDRNV1Z4TkhWQk5ETXpVVXBoZVVoa1ZHazRjM2h0T0hGa1lrRmlibFI1Wnpsa2MxaERha1E0VGs0M1JYUmpjalJtTlRWdFVtaHVPVlF4WkROa05rVmpOa2huZEhCalZXWmxiV0kwV2xaTFUwTkVZVUp5UW5sa2MzSkxRVUl6VkV0WFRsaEJhMmR1ZWpGb2MyVmxjV1k0V1NJc0ltbHpjeUk2SW1ScFpEcGxZbk5wT25wNFlWbGhWWFJpT0hCMmIwRjBXVTVYWWt0amRtVm5JaXdpYm1KbUlqb3hOak0xTnpJME9EQXdMQ0psZUhBaU9qRTVOVE0zTmpNeU1EQXNJbWxoZENJNk1UVTVNamd6TlRFd05Dd2lkbU1pT25zaVFHTnZiblJsZUhRaU9sc2lhSFIwY0hNNkx5OTNkM2N1ZHpNdWIzSm5Mekl3TVRndlkzSmxaR1Z1ZEdsaGJITXZkakVpWFN3aWFXUWlPaUoxY200NmRYVnBaRG93TUROaE1XUmtPQzFoTldReUxUUXlaV1l0T0RFNE1pMWxPVEl4WXpCaE9XWXlZMlFpTENKMGVYQmxJanBiSWxabGNtbG1hV0ZpYkdWRGNtVmtaVzUwYVdGc0lpd2lWbVZ5YVdacFlXSnNaVUYwZEdWemRHRjBhVzl1SWwwc0ltbHpjM1ZsY2lJNkltUnBaRHBsWW5OcE9ucDRZVmxoVlhSaU9IQjJiMEYwV1U1WFlrdGpkbVZuSWl3aWFYTnpkV0Z1WTJWRVlYUmxJam9pTWpBeU1TMHhNUzB3TVZRd01Eb3dNRG93TUZvaUxDSjJZV3hwWkVaeWIyMGlPaUl5TURJeExURXhMVEF4VkRBd09qQXdPakF3V2lJc0luWmhiR2xrVlc1MGFXd2lPaUl5TURVd0xURXhMVEF4VkRBd09qQXdPakF3V2lJc0ltVjRjR2x5WVhScGIyNUVZWFJsSWpvaU1qQXpNUzB4TVMwek1GUXdNRG93TURvd01Gb2lMQ0pwYzNOMVpXUWlPaUl5TURJd0xUQTJMVEl5VkRFME9qRXhPalEwV2lJc0ltTnlaV1JsYm5ScFlXeFRkV0pxWldOMElqcDdJbWxrSWpvaVpHbGtPbXRsZVRwNlFtaENURzFaYlhscGFIUnZiVkprU2twT1JVdDZZbEJxTlRGdk5HRXpSMWxHWlZwdlVraFRRVUpMVlhkeFpHcHBVVkJaTW1OeE0weFVSMUp4TXpaU2FHOWFVbkZwZURGbGNUUjFRVFF6TTFGS1lYbElaRlJwT0hONGJUaHhaR0pCWW01VWVXYzVaSE5ZUTJwRU9FNU9OMFYwWTNJMFpqVTFiVkpvYmpsVU1XUXpaRFpGWXpaSVozUndZMVZtWlcxaU5GcFdTMU5EUkdGQ2NrSjVaSE55UzBGQ00xUkxWMDVZUVd0bmJub3hhSE5sWlhGbU9Ga2lmU3dpWTNKbFpHVnVkR2xoYkZOamFHVnRZU0k2ZXlKcFpDSTZJbWgwZEhCek9pOHZZWEJwTFhCcGJHOTBMbVZpYzJrdVpYVXZkSEoxYzNSbFpDMXpZMmhsYldGekxYSmxaMmx6ZEhKNUwzWXpMM05qYUdWdFlYTXZlak5OWjFWR1ZXdGlOekl5ZFhFMGVETmtkalY1UVVwdGJrNXRla1JHWlVzMVZVTTRlRGd6VVc5bFRFcE5JaXdpZEhsd1pTSTZJa1oxYkd4S2MyOXVVMk5vWlcxaFZtRnNhV1JoZEc5eU1qQXlNU0o5TENKMFpYSnRjMDltVlhObElqcDdJbWxrSWpvaWFIUjBjSE02THk5aGNHa3RjR2xzYjNRdVpXSnphUzVsZFM5MGNuVnpkR1ZrTFdsemMzVmxjbk10Y21WbmFYTjBjbmt2ZGpVdmFYTnpkV1Z5Y3k5a2FXUTZaV0p6YVRwNmVHRlpZVlYwWWpod2RtOUJkRmxPVjJKTFkzWmxaeTloZEhSeWFXSjFkR1Z6TDJJME1HWmtPV0kwTURRME1UaGhORFJrTW1RNU9URXhNemMzWVRBek1UTXdaR1JsTkRVd1pXSTFORFpqTnpVMVlqVmlPREJoWTJRM09ESTVNREpsTm1RaUxDSjBlWEJsSWpvaVNYTnpkV0Z1WTJWRFpYSjBhV1pwWTJGMFpTSjlmWDAuZktDUkVzd0c0M184NjJWcjhMM2xKT1JnRk56dk1aMmhSN3A5M2dmRWtoTS1xaElJbFNsUDBBY0FneTBjNnF1Ml8ydUFJQzdtT0duajlBWjNBdTJuTHciXX0sIm5iZiI6MTYzNTcyNDgwMCwiZXhwIjoxOTUzNzYzMjAwfQ.hp99g7ue2m0e2XAJd0Z707UGSpL2kVNGFFaK7CtzUuk0POMPUJBZ6vCKa4AxseQV6dDYSulZMTkOlMNAFdZnxw
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 = {
// OPTIONAL. Timeout after which the requests made by the library will fail. Default: 15 seconds
// timeout: 15_000,
// OPTIONAL. Determines whether the JSON to JWT transformation will remove the original fields from the input payload.
// Default: true
// removeOriginalFields: true,
// 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 credential subject or not
// Validation is active by default.
// skipCredentialSubjectValidation: false,
// OPTIONAL. Unix timestamp. Optional comparison date. Default: current date and time.
// 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. Credential subject. This parameter is mandatory if the payload's `credentialSubject` is an array.
// It must correspond to one of the IDs in the payload's `credentialSubject` array.
// sub: "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsNgeztBFXEB9FUZCoufTjXiTUZYKkcP36i2XAQCphfxBwvXG4dAaF6pdwhrMGyaLMC81fU5ECMnt4VgMQpwh3sn5vSbUpwoaTBME78noXJaTLgkCv5KkM6VgGTfWUjH8Z2",
// OPTIONAL. Extra credentialSchema types. By default, the library only supports "FullJsonSchemaValidator2021" and "JsonSchema".
// The library is not responsible for validating these extra types.
// extraCredentialSchemaTypes: [],
// 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,
config,
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'
]
}
*/
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");
Copyright (C) 2025 European Union
This program is free software: you can redistribute it and/or modify it under the terms of the EUROPEAN UNION PUBLIC LICENCE v. 1.2 as published by the European Union.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the EUROPEAN UNION PUBLIC LICENCE v. 1.2 for further details.
You should have received a copy of the EUROPEAN UNION PUBLIC LICENCE v. 1.2. along with this program. If not, see https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12.