Skip to main content
European CommissionEBSI European Blockchain

How to verify a credential

Last updated on

Introduction

Verifiable credentials are crucial in establishing trust and authenticity in the digital world. Whether you’re a student receiving a university diploma or an employee obtaining a professional certification, verifiable credentials provide a secure way to prove your qualifications. This guide breaks down the key components of Verifiable Credentials (VCs) and Verifiable Presentations (VPs) and explains their verification processes using EBSI libraries.

Key components

TermDescriptionExample
Credential SubjectThe individual or entity to whom the credential applies.The recipient of a diploma is the credential subject.
IssuerThe organisation that issues the credential.Think of it as the university granting the diploma or the certification authority validating the skills.
Issuance DateIndicates when the credential was issued.Similar to the timestamp on a diploma or certificate.
Proofs (Signatures)Cryptographic signatures that ensure the credential’s authenticity and integrity.Imagine it as a digital seal from the issuer, guaranteeing authenticity.
Expiration Date(Optional) Specifies when the credential becomes invalid.Professional certifications may need renewal after a certain period.
StatusIndicates whether the credential is still valid.If the issuer revokes the credential, its status changes.
Custom PropertiesProvides specific details about the credential.If a verifier needs to determine whether a subject is older than 21 years of age, they might rely on a specific birthdate property or more abstract properties, such as ageOver.
info

For more information on the data fields used by verifiers in the validation process, refer to this page.

Resolving resources

Verifiable credentials and presentations may reference EBSI resources — such as a JSON schema from the Trusted Schemas Registry or an accreditation from the Trusted Issuers Registry — using 2 different methods.

The resources can either be referenced by their URL, or by an URI following the EBSI URI scheme. When they are referenced by an URL, it is recommended to not follow the URL directly, but rather to replace the hostname by the hostname of one of the trusted nodes, as defined in the Trusted Nodes List.

Verifiable Credential JWT Verification Process

The verification process involves examining various data fields and properties of the VC. The following requirements and checks should be considered when verifying the credential:

1. Header

  • Ensure the algorithm (alg) is ES256, ES256K, Ed25519, or EdDSA.
  • The kid property must contain the issuer’s DID and the fragment identifier for the verification method.

2. Validating VC payload properties

  • Verify the VC payload
    • The payload must contain a vc property with an EBSI Verifiable Attestation. It's advisable to implement extra validation checks here. Some examples include:
      • Validation of @context: This provides essential context information for interpreting the credential. Take into account that the first value in the @context set must be "https://www.w3.org/2018/credentials/v1" (as defined here).
      • Validation of type: Determines the purpose and usage of the VC. Please note that the first value of the type set must be VerifiableCredential (for further details, please refer here).
      • Validation of dates: Ensure dates (e.g., issuance date, valid-from date, expiration date) are consistent and within acceptable ranges. Invalid or inconsistent dates may indicate tampering or errors.
    • The iss property must match the VC issuer (vc.issuer).
    • The sub property must match the VC credential subject (vc.credentialSubject.id).
    • The jti property must match the VC ID (vc.id).
    • The iat property must refer to the date in VC issued (vc.issued).
    • The nbf property must refer to the date in VC valid from (vc.validFrom).
    • The exp property must refer to the date in VC expiration date (vc.expirationDate), if defined.

3. Signature Validation

  • Validate the signature against the verification method from the DID document corresponding to the VC JWT kid header.
  • If the issuer is a Legal Entity, ensure the issuer is registered in the Trusted Issuers Registry (TIR). This registry ensures that only authorised entities issue VCs.
  • Additionally, if the VC is an attestation with accreditation:
    • The VC must contain a termsOfUse property pointing to the accreditations of the issuer.
    • The issuer must be accredited to issue the types present in the credential.

5. Credential Subject

  • The credential subject must be a valid Decentralised Identifier (DID). Choose either:

6. Credential Schema

  • The VC credential schema(s) must link to valid EBSI credential schemas registered in the Trusted Schemas Registry (TSR). The VC must extend the EBSI base Verifiable Attestation schema. These schemas define the structure and properties of the credentials.
tip

To verify VCs in JSON Web Token (JWT) format, you can either leverage EBSI's Verifiable Credential library or develop your own solution.

The library simplifies the process and ensures optimal security. If you choose not to use the library, follow the VC verification process described above. The example below demonstrates how to verify a VC using the verifyCredentialJwt function in EBSI's library.

Verifying a VC JWT using the verifyCredentialJwt function in VC library

Expand for the VC example
 import {
verifyCredentialJwt,
type VerifyCredentialOptions,
} from "@cef-ebsi/verifiable-credential";

const vcJwt =
"eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QiLCJraWQiOiJkaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZyNDSHhZek9xdDM4U3g2WUJmUFloaUVkZ2N3eldrOXR5N2swTEJhNmg3MG5jIn0.eyJqdGkiOiJ1cm46dXVpZDowMDNhMWRkOC1hNWQyLTQyZWYtODE4Mi1lOTIxYzBhOWYyY2QiLCJzdWIiOiJkaWQ6a2V5OnoyZG16RDgxY2dQeDhWa2k3SmJ1dU1tRllyV1BnWW95dHlrVVozZXlxaHQxajlLYnNOZ2V6dEJGWEVCOUZVWkNvdWZUalhpVFVaWUtrY1AzNmkyWEFRQ3BoZnhCd3ZYRzRkQWFGNnBkd2hyTUd5YUxNQzgxZlU1RUNNbnQ0VmdNUXB3aDNzbjV2U2JVcHdvYVRCTUU3OG5vWEphVExna0N2NUtrTTZWZ0dUZldVakg4WjIiLCJpc3MiOiJkaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZyIsIm5iZiI6MTYzNTcyNDgwMCwiZXhwIjoxOTUzNzYzMjAwLCJpYXQiOjE2MzU1NTIwMDAsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sImlkIjoidXJuOnV1aWQ6MDAzYTFkZDgtYTVkMi00MmVmLTgxODItZTkyMWMwYTlmMmNkIiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlZlcmlmaWFibGVBdHRlc3RhdGlvbiJdLCJpc3N1ZXIiOiJkaWQ6ZWJzaTp6eGFZYVV0Yjhwdm9BdFlOV2JLY3ZlZyIsImlzc3VhbmNlRGF0ZSI6IjIwMjEtMTEtMDFUMDA6MDA6MDBaIiwidmFsaWRGcm9tIjoiMjAyMS0xMS0wMVQwMDowMDowMFoiLCJ2YWxpZFVudGlsIjoiMjA1MC0xMS0wMVQwMDowMDowMFoiLCJleHBpcmF0aW9uRGF0ZSI6IjIwMzEtMTEtMzBUMDA6MDA6MDBaIiwiaXNzdWVkIjoiMjAyMS0xMC0zMFQwMDowMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDprZXk6ejJkbXpEODFjZ1B4OFZraTdKYnV1TW1GWXJXUGdZb3l0eWtVWjNleXFodDFqOUtic05nZXp0QkZYRUI5RlVaQ291ZlRqWGlUVVpZS2tjUDM2aTJYQVFDcGhmeEJ3dlhHNGRBYUY2cGR3aHJNR3lhTE1DODFmVTVFQ01udDRWZ01RcHdoM3NuNXZTYlVwd29hVEJNRTc4bm9YSmFUTGdrQ3Y1S2tNNlZnR1RmV1VqSDhaMiJ9LCJjcmVkZW50aWFsU2NoZW1hIjp7ImlkIjoiaHR0cHM6Ly9hcGktcGlsb3QuZWJzaS5ldS90cnVzdGVkLXNjaGVtYXMtcmVnaXN0cnkvdjMvc2NoZW1hcy96M01nVUZVa2I3MjJ1cTR4M2R2NXlBSm1uTm16REZlSzVVQzh4ODNRb2VMSk0iLCJ0eXBlIjoiRnVsbEpzb25TY2hlbWFWYWxpZGF0b3IyMDIxIn0sInRlcm1zT2ZVc2UiOnsiaWQiOiJodHRwczovL2FwaS1waWxvdC5lYnNpLmV1L3RydXN0ZWQtaXNzdWVycy1yZWdpc3RyeS92NS9pc3N1ZXJzL2RpZDplYnNpOnp4YVlhVXRiOHB2b0F0WU5XYktjdmVnL2F0dHJpYnV0ZXMvYjQwZmQ5YjQwNDQxOGE0NGQyZDk5MTEzNzdhMDMxMzBkZGU0NTBlYjU0NmM3NTViNWI4MGFjZDc4MjkwMmU2ZCIsInR5cGUiOiJJc3N1YW5jZUNlcnRpZmljYXRlIn19fQ.I8Im8azp0pSnM4z_jqGTTfYUg7K802POR2LTJftVfjYtMt82Cik2Z_KGOG7dHhx13R6VGVZKg9134ke1bKhtPw";

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,
} satisfies VerifyCredentialOptions;

const verifiedVc = await verifyCredentialJwt(vcJwt, options);

console.log(verifiedVc);
/*
{
'@context': [ 'https://www.w3.org/2018/credentials/v1' ],
id: 'urn:uuid:003a1dd8-a5d2-42ef-8182-e921c0a9f2cd',
type: [ 'VerifiableCredential', 'VerifiableAttestation' ],
issuer: 'did:ebsi:zxaYaUtb8pvoAtYNWbKcveg',
issuanceDate: '2021-11-01T00:00:00Z',
validFrom: '2021-11-01T00:00:00Z',
validUntil: '2050-11-01T00:00:00Z',
expirationDate: '2031-11-30T00:00:00Z',
issued: '2021-10-30T00:00:00Z',
credentialSubject: {
id: 'did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsNgeztBFXEB9FUZCoufTjXiTUZYKkcP36i2XAQCphfxBwvXG4dAaF6pdwhrMGyaLMC81fU5ECMnt4VgMQpwh3sn5vSbUpwoaTBME78noXJaTLgkCv5KkM6VgGTfWUjH8Z2'
},
credentialSchema: {
id: 'https://api-pilot.ebsi.eu/trusted-schemas-registry/v3/schemas/z3MgUFUkb722uq4x3dv5yAJmnNmzDFeK5UC8x83QoeLJM',
type: 'FullJsonSchemaValidator2021'
},
termsOfUse: {
id: 'https://api-pilot.ebsi.eu/trusted-issuers-registry/v5/issuers/did:ebsi:zxaYaUtb8pvoAtYNWbKcveg/attributes/b40fd9b404418a44d2d9911377a03130dde450eb546c755b5b80acd782902e6d',
type: 'IssuanceCertificate'
}
}
*/

Verifiable Presentation JWT Verification Process

The verification process involves examining various data fields and properties of the VP. The following requirements and checks should be considered when validating the presentation:

1. Header

  • Ensure the algorithm (alg) is ES256, ES256K, Ed25519, or EdDSA.
  • The kid property contains the holder’s DID and the fragment identifier for the verification method.

2. Validating VP payload properties

  • Verify the VP payload
    • id (optional): Provides a unique identifier for the presentation.
    • type: Expresses the type of presentation (e.g., VerifiablePresentation). Please note that the first value of the type set must be VerifiablePresentation.
    • verifiableCredential: Constructed from one or more VC JWTs, all validated individually. Check VC verification process explained above.
    • holder: A URI for the entity generating the presentation.

For more information on VP properties, refer to this page.

3. Signature Validation

  • Validate the signature against the verification method from the DID document corresponding to the VP JWT kid header.

4. Credential Subject

  • The credential subject must be a valid Decentralised Identifier (DID). Choose either:

The VP subject should match the subject of the credentials included in the VP.

5. Credential Schema

  • The VC credential schema(s) must link to valid EBSI credential schemas registered in the TSR. The VP must extend the EBSI base Verifiable Presentation schema. These schemas define the structure and properties of the credentials.
tip

To verify VPs in JSON Web Token (JWT) format, you can either leverage EBSI's Verifiable Presentation library or develop your own solution.

The library simplifies the process and ensures optimal security. If you choose not to use the library, follow the VP verification process described above. The example below demonstrates how to verify a VP using the verifyPresentationJwt function in EBSI's library.

6. Verifying a VP JWT using the verifyPresentationJwt function in VP library

Expand for the VP example
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'
]
}
*/

Mapping JWT to VC/VP properties

For backward compatibility with JWT processors, use the following mappings:

  • exp: Represents the expirationDate property (encoded as a UNIX timestamp).
  • iss: Represents the issuer property of a VC or the holder property of a VP.
  • nbf: Represents the issuance date (encoded as a UNIX timestamp).
  • jti: Represents the ID property of the VC or VP.
  • sub: Represents the ID property contained in the credential subject.
  • aud: Represents (i.e., identify) the intended audience of the verifiable presentation (i.e., the verifier intended by the presenting holder to receive and verify the verifiable presentation).

The following rules apply to JOSE headers in the context of this specification:

  • alg MUST be set for digital signatures. If only the proof property is needed for the chosen signature method (that is, if there is no choice of algorithm within that method), the alg header MUST be set to none.
  • kid MAY be used if there are multiple keys associated with the issuer of the JWT. The key discovery is outside the scope of this specification. For example, the kid can refer to a key in a DID document or can be the identifier of a key inside a JWKS.
  • typ, if present, MUST be set to "JWT".

For more information on JWT encoding, please refer here.