Verifier Integration

Link the Trust Registry to a Verifier2 Service to enable automatic trust verification during credential presentation. This allows the etsi-trust-list policy to resolve issuer certificates without external network calls at verification time.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                     Verification Flow                            │
│                                                                  │
│  Credential  ──►  Verifier2  ──►  etsi-trust-list policy        │
│                       │                    │                     │
│                       │ dependency         │ resolves via        │
│                       ▼                    ▼                     │
│              Trust Registry Service  ◄─────┘                     │
│                       │                                          │
│                       │ queries                                  │
│                       ▼                                          │
│                   Loaded Trust Sources (TSL, LoTE)               │
└─────────────────────────────────────────────────────────────────┘

Prerequisites

  1. A Trust Registry Service with at least one trust source loaded (see Setup and Trust Source Management).
  2. A Verifier2 Service in the same tenant.

Add the Trust Registry as a dependency of your Verifier2 service:

CURL

Endpoint: /v1/{target}/verifier2-service-api/dependencies/add

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{verifier2Target}/verifier2-service-api/dependencies/add' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: text/plain' \
  -d 'myorg.tenant1.trust-registry'

Path Parameters

  • orgID: String — Your organization's Base URL prefix.
  • verifier2Target: String — The Verifier2 service path, e.g. myorg.tenant1.verifier2.

Header Parameters

  • Authorization: String — Bearer token for authentication. Format: Bearer {yourToken}.

Body

Plain text containing the Trust Registry service path, e.g. myorg.tenant1.trust-registry.

Response Codes

  • 201 — Dependency added successfully.

The body must be sent as text/plain, not JSON. The value is the full path to the Trust Registry service.

List the Verifier2 dependencies to confirm the Trust Registry is linked:

CURL

Endpoint: GET /v1/{verifier2Target}/verifier2-service-api/dependencies/list

Example Request
curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{verifier2Target}/verifier2-service-api/dependencies/list' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}'

Path Parameters

  • orgID: String — Your organization's Base URL prefix.
  • verifier2Target: String — The Verifier2 service path, e.g. myorg.tenant1.verifier2.

Header Parameters

  • Authorization: String — Bearer token for authentication. Format: Bearer {yourToken}.

Example Response

Returns an array of all services registered as dependencies of the Verifier2 service.

[
  {
    "_id": "myorg.tenant1.trust-registry",
    "type": "trust-registry"
  }
]

Use the etsi-trust-list Policy

The etsi-trust-list policy is a standard Verifier2 VC policy. You add it to the vc_policies array when creating a verification session — the same way you would add signature or any other policy.

The policy snippet looks like this:

{
  "policy": "etsi-trust-list",
  "expectedEntityType": "PID_PROVIDER",
  "allowStaleSource": false,
  "requireAuthenticated": true
}

Place this inside the policies.vc_policies array of your session creation request body. For a complete walkthrough of creating a verification session — including the full request structure, flow_type, dcql_query, and response fields — see Credential Verification.

When Verifier2 has the Trust Registry linked as a dependency (as set up above), the policy resolves certificates automatically using the pre-loaded trust sources. No additional URL or inline configuration is required.

Certificate Chain Construction

The policy sends the complete leaf-first credential chain to the linked Trust Registry. The registry uses certificates stored in loaded trust sources as independent trust anchors and performs PKIX path building.

The credential should contain:

  1. the credential-signing leaf certificate;
  2. any intermediate certificates required to reach the registered anchor.

Do not include the root trust anchor when the applicable profile prohibits it. OpenID4VC HAIP 1.0, Section 6.1.1 states that the X.509 trust-anchor certificate MUST NOT be included in the SD-JWT VC x5c header. The Trust Registry must contain the anchor certificate itself, not only its SHA-256 fingerprint, so it can construct the certification path.

Policy Resolution Modes

The etsi-trust-list policy supports three resolution modes. Choose the one that fits your deployment:

If more than one mode is configured, precedence is remote service (trustRegistryUrl), inline sources (trustLists), then the linked Enterprise service.

Uses the Trust Registry you linked in the previous step. The policy discovers and queries it automatically at verification time — no extra configuration needed.

{
  "policy": "etsi-trust-list",
  "expectedEntityType": "PID_PROVIDER"
}

This is the recommended mode for enterprise deployments. Trust lists are pre-loaded into the Trust Registry Service, so verification requires no outbound network calls.

2. Remote Service Mode

Queries a compatible external Trust Registry API. The policy appends /trust-registry/resolve/certificate-chain to trustRegistryUrl and does not attach an Enterprise bearer token.

{
  "policy": "etsi-trust-list",
  "trustRegistryUrl": "https://trust-registry.example.com",
  "expectedEntityType": "PID_PROVIDER"
}

trustRegistryUrl is not an Enterprise service target URL. Use linked service mode for an Enterprise Trust Registry dependency. Remote mode requires an API that exposes POST /trust-registry/resolve/certificate-chain with suitable network access and authentication.

3. Inline Mode

Fetches and processes a trust list directly at verification time, without a Trust Registry service. Suitable for testing or simple deployments where operating a dedicated Trust Registry Service is not warranted.

{
  "policy": "etsi-trust-list",
  "trustLists": [
    "https://www.signatur.rtr.at/vertrauensliste.xml"
  ],
  "expectedEntityType": "PID_PROVIDER"
}

Inline Mode fetches the trust list on every verification request. This adds latency and creates a runtime dependency on the availability of the external URL. Avoid this mode in production.

With validateSignatures: true, inline mode verifies source signature integrity. Use requireAuthenticated: true together with independently configured signer certificates when the source signer must also be authorized.

Policy Configuration Options

The following parameters are supported across all resolution modes unless noted otherwise:

ParameterTypeDefaultDescription
expectedEntityTypestringnullFilter by entity type. Valid values: PID_PROVIDER, WALLET_PROVIDER, ATTESTATION_PROVIDER, TRUST_SERVICE_PROVIDER, ACCESS_CERTIFICATE_PROVIDER, RELYING_PARTY_PROVIDER, OTHER. When omitted, no entity type filter is applied.
expectedServiceTypestringnullFilter by service type URI. When omitted, no service type filter is applied.
allowStaleSourcebooleanfalseWhen true, accepts STALE_SOURCE decisions and TRUSTED decisions whose source freshness is STALE. A STALE_SOURCE decision can represent an expired source, so keep this false for strict verification.
requireAuthenticatedbooleanfalseWhen true, requires AUTHENTICATED source assurance in every freshness branch. FAILED assurance is always rejected. When false, INTEGRITY_VERIFIED, UNVERIFIED, or UNKNOWN may be accepted if the source was admitted by its configured policy.
trustRegistryUrlstring(Remote mode only) Base URL of a compatible service exposing /trust-registry/resolve/certificate-chain.
trustListsarray of strings(Inline mode only) One or more trust list URLs or raw XML/JSON/JWS values to process at verification time.
validateSignaturesbooleantrue(Inline mode only) When true, verifies XMLDSig or compact-JWS signatures when present. When false, signature verification is skipped.
trustedSourceSignerCertificatesarray of strings[](Inline mode only) PEM or Base64-DER signer certificates or trust anchors used to authenticate XMLDSig and compact-JWS sources.

Example Configurations

Strict linked-service mode — entity type enforced, stale sources rejected, and the previously loaded source must be authenticated:

{
  "policy": "etsi-trust-list",
  "expectedEntityType": "PID_PROVIDER",
  "allowStaleSource": false,
  "requireAuthenticated": true
}

The linked Trust Registry must have admitted the source with REQUIRE_AUTHENTICATED; setting requireAuthenticated on the verification policy does not authenticate a source retroactively.

Permissive development mode — useful for controlled testing when trust sources are not independently authenticated:

{
  "policy": "etsi-trust-list",
  "expectedEntityType": "PID_PROVIDER",
  "allowStaleSource": true,
  "requireAuthenticated": false
}

Verification Result

Once a wallet has responded to the verification request and the session is complete, retrieve the session result using the session info endpoint. The policyResults field contains one entry per applied policy.

For the etsi-trust-list policy, a successful result looks like this:

{
  "policy": "etsi-trust-list",
  "success": true,
  "result": {
    "trusted": true,
    "decision": "TRUSTED",
    "matchedEntity": {
      "entityId": "entity-123",
      "entityType": "PID_PROVIDER",
      "legalName": "Example PID Provider",
      "country": "DE"
    },
    "matchedService": {
      "serviceId": "service-456",
      "serviceType": "http://uri.etsi.org/TrstSvc/Svctype/IdV",
      "status": "GRANTED"
    },
    "matchedSource": {
      "sourceId": "pid-providers",
      "sourceFamily": "LOTE",
      "format": "ETSI_TS_119_602_JSON",
      "displayName": "EU PID Providers"
    },
    "sourceFreshness": "FRESH",
    "authenticity": "AUTHENTICATED"
  }
}

Result fields:

  • trusted: Always true for a successful policy result.
  • decision: The trust resolution outcome. TRUSTED means the issuer was found in a valid trusted source. STALE_SOURCE means the source was found but is stale — only returned as a success when allowStaleSource: true is set.
  • matchedEntity (optional): The entity in the trust source whose certificate matched.
    • entityId: The entity's identifier within the trust source.
    • entityType: The type of the entity, e.g. PID_PROVIDER, WALLET_PROVIDER, ATTESTATION_PROVIDER.
    • legalName: The registered legal name of the entity.
    • country (optional): The country code of the entity, when available.
  • matchedService (optional): The specific trust service entry that matched the certificate.
    • serviceId: The service's identifier within the trust source.
    • serviceType: The service type URI as defined in the trust list.
    • status: The service status URI as defined in the trust list.
  • matchedSource: The trust source that produced the match.
    • sourceId: The ID of the trust source as registered in the Trust Registry.
    • sourceFamily: The trust list family, e.g. TSL or LOTE.
    • displayName: The human-readable name of the trust source.
  • sourceFreshness: Freshness state of the trust source at verification time. Possible values: FRESH, STALE, EXPIRED, UNKNOWN.
  • authenticity: Source assurance projection. Possible values: AUTHENTICATED, INTEGRITY_VERIFIED, UNVERIFIED, FAILED, or UNKNOWN.
  • warnings (optional): Array of warning strings, present only when the policy succeeded with caveats (e.g. stale source accepted).

Troubleshooting Verification

  • No trust source configured: link a Trust Registry dependency, set trustRegistryUrl, or provide trustLists.
  • Trust source is not authenticated: load the source with REQUIRE_AUTHENTICATED and an independently trusted signer certificate, or correct the inline signer configuration.
  • Trust source is stale or expired: refresh the source and inspect its nextUpdate value. Enable allowStaleSource only after assessing the risk.
  • No valid path: ensure the credential presents the leaf and required intermediates, while the Trust Registry stores the full anchor certificate.
Last updated on July 27, 2026