OpenResidency Docs

The Verifiable Credentials model

Issuer, Holder, and Verifier — the three roles of the W3C Verifiable Credentials triangle, and the difference between verifying a credential and verifying a presentation.

In plain terms. This works the way a passport does. One authority issues it, the person carries it, and anyone can check it is genuine without ringing up the authority that issued it. Issuer, holder and verifier below are just names for those three parties.

Everything in OpenResidency rests on the W3C Verifiable Credentials (VC) model. It has exactly three roles. Get these straight and the rest of the system falls into place.

The three roles

RoleWhat it doesIn OpenResidency
IssuerCreates and signs credentialsThe State Residency Authority (a deployment of OpenResidency)
HolderHolds the credential and presents itThe citizen / resident, via a wallet
VerifierReceives a credential and checks itAnyone confirming residency — a clinic, checkpoint, bank, or sector service

The credential travels from the issuer, through the holder, to a verifier. The issuer and verifier never need to talk to each other — the credential is self-contained and the verifier checks it against the issuer's published keys.

The fourth element: the Verifiable Data Registry

The reason the issuer and verifier never talk is a shared, published source of truth — the Verifiable Data Registry. In OpenResidency it's the issuer's .well-known endpoints: the DID document (public keys) and the Bitstring Status List (revocation). The issuer publishes to it; the verifier reads from it. That indirection is exactly what lets a credential be checked offline, with the issuer never in the loop at verification time.

Subject ≠ Holder

The citizen is the subject — the credential is about them. The wallet is the holder — it possesses and presents it. They're usually the same party, and holder binding is what forces them to coincide: a credential bound to the holder's key can't be presented by someone who merely copied the bytes.

The passport analogy

  • A credential is like a passport: a signed, tamper-evident document making a claim ("resident of Katsina").
  • The issuer is the passport office; the holder is you; the verifier is the border agent.
  • Verifying is checking the passport is genuine — against the issuer's official seal — without phoning the passport office.

Verifying a credential vs verifying a presentation

This is the single most important distinction in the system, and it's why there are two verifiers in the code.

A credential check (VcVerifier) answers: "is this a genuine, unexpired, unrevoked credential?" It checks the issuer's signature, the expiry, and revocation. But every one of those checks passes for a credential copied from someone else — on its own, a credential is a bearer token: whoever holds the bytes can use it.

A presentation check (VpVerifier) answers the questions that matter when a real person is in front of you: "is the person presenting it its holder, and did they present it to me, just now?" It adds three checks on top of credential validity:

  1. Holder binding — the presentation is signed by the key the credential was issued to.
  2. Freshness — the nonce is one the verifier just issued, and it's single-use (no replay).
  3. Audience — the presentation names this verifier (can't be replayed elsewhere).

Drop any one and it's a bearer token again

Holder binding, nonce, and audience are not optional hardening — they are what stop a stolen or copied credential from being used by someone else. This is why they appear in the project's "What not to break" list.

Back to the analogy: VcVerifier confirms the passport is real; VpVerifier also confirms the person holding it is its owner (the photo/biometric match) and is presenting it to you, live (not a photocopy replayed at another gate).

In the code

  • Credential check → VcVerifier
  • Presentation check → VpVerifier (wraps VcVerifier for the credential inside)

Next: see how these abstract roles map onto OpenResidency's concrete parties in Roles & role mapping.

On this page