light-mode-image
Learn

How to issue verifiable credentials in your application

A business and developer guide to issuing verifiable credentials using OID4VCI, covering architecture decisions, required components, optional integrations, and deployment considerations.

Issuing verifiable credentials—such as mobile driver's licences (mDLs), employee badges, health cards, or proof-of-age tokens—requires orchestrating identity verification, data sourcing, cryptographic signing, and secure delivery to a holder's wallet. As an implementer, you need to understand the components involved and how they fit together within your existing systems.

This guide walks you through the key architectural decisions for building a credential issuance solution using MATTR VII, from selecting your issuance workflow through to managing credential lifecycle.

How credential issuance works

At its core, credential issuance involves three parties:

  1. Issuer: Your organisation, using MATTR VII to create and sign credentials.
  2. Holder: The end user who receives and stores the credential in their wallet.
  3. Wallet: An application that claims, stores, and later presents the credential.

The issuance process follows the OpenID for Verifiable Credential Issuance (OID4VCI) standard. Your application creates a credential offer, the holder's wallet resolves issuer metadata, authenticates (if required), and receives a cryptographically signed credential.

The result is a credential that is:

  • Tamper-evident: Any modification invalidates the signature.
  • Verifiable: Any relying party can confirm authenticity against the issuer's certificate chain without contacting the issuer.
  • Portable: Stored in the holder's wallet and presentable across contexts.
  • Revocable: Status can be updated after issuance.

Choose your issuance workflow

MATTR VII supports two OID4VCI workflows. Your choice depends on how much control you need over user authentication during the claiming process.

Pre-authorized Code flow

Best for: issuing to known users, silent issuance within existing app sessions, high-assurance credentials where identity has already been verified out-of-band.

The issuer authenticates the user externally, prepares the credential data, and creates a single-use offer. The wallet claims the credential without an additional authentication step.

  • Offers are single-use — consumed after successful claim.
  • Supports mDocs credential format.
  • Optional transaction code adds two-factor security.
  • Ideal for in-app issuance or silent credential updates.

Components involved:

ComponentRole
Credential offerContains pre-authorized code and claim data
Credential configurationDefines credential structure and claim mappings
Claims source (optional)Enriches credential with additional data

See the Pre-authorized Code flow overview for the detailed workflow and configuration steps.

Authorization Code flow

Best for: public-facing credential offers, user self-service portals, scenarios requiring real-time identity verification.

The holder scans a QR code or clicks a link, authenticates through your identity provider, and the credential is issued upon successful authentication.

  • Offers are reusable: Multiple users can claim from the same offer.
  • Supports mDocs and CWT credential formats.
  • Integrates with your existing OIDC identity provider.
  • Supports optional interaction hooks for additional verification steps.

Components involved:

ComponentRole
Credential offerEntry point that starts the flow
Authentication providerAuthenticates the holder via OIDC
Credential configurationDefines credential structure and claim mappings
Claims source (optional)Fetches additional data from external systems
Interaction hook (optional)Adds custom steps between auth and issuance

See the Authorization Code flow overview for the detailed workflow and configuration steps.

Define your credential structure

Before issuing, you need to define what data the credential will contain and how it maps from your source systems.

Credential configuration

A credential configuration is the template that defines:

  • Credential type and format: mDocs (ISO/IEC 18013-5) or CWT.
  • Claim mappings: How source data maps to credential attributes, organized by namespace.
  • Validity rules: validFrom, validUntil, or relative expiry (expiresIn).
  • Revocation: Whether to include status list references.
  • Branding: Display metadata for wallet rendering (name, logo, colors).

Credential data mapping

Map your existing data models (e.g., from legacy digital credentials or other data sources) to the relevant ISO/IEC 18013-5 (or equivalent) schema. All claim mapping logic, including translation of custom or legacy fields, should occur in your claims source or be handled before passing data to the credential configuration.

Claim data sources

Claims can come from multiple sources depending on your workflow:

SourceAvailable inDescription
Authentication provider (ID token)Authorization CodeClaims from the user's OIDC authentication
Interaction hook responseAuthorization CodeClaims returned by your custom interaction step
Credential offer payloadPre-authorized CodeClaims supplied directly when creating the offer
Claims sourceBoth flowsExternal API call to fetch additional data

Deliver credential offers to holders

The credential offer is what starts the issuance flow for the holder. You need to decide how offers reach your users and which wallet applications can claim them.

Offer delivery methods

MethodBest forDescription
QR codeIn-person kiosks, printed materialsUser scans with their wallet app
Deep linkEmail, SMS, in-app notificationsClickable URL that opens the wallet
Silent pushExisting app sessionsCredential delivered without user initiation

Wallet targeting

You can control which wallet apps can claim your offers:

  • Open model — any OID4VCI-compatible wallet can claim using the standard openid-credential-offer:// scheme.
  • Private-use scheme — a custom URI scheme targets specific wallet applications.
  • Claimed HTTPS links — App Links (Android) or Universal Links (iOS) provide the strongest app-binding with domain verification.
  • Wallet attestation — requires wallets to cryptographically prove their authenticity before claiming credentials. This provides the strongest level of wallet trust by validating the wallet instance through a certificate-based trust chain, ensuring only authorized wallet applications can receive your credentials.

See claiming credential offers for detailed configuration guidance.

Optional components

These components extend the basic issuance workflow with additional capabilities.

Authentication provider

An authentication provider is your existing OIDC-compliant identity provider (e.g., Auth0, Entra ID, Okta). It authenticates the holder during the Authorization Code flow.

Requirements:

  • Must support OIDC Discovery (.well-known/openid-configuration).
  • Must support the authorization code grant.
  • Must support the state parameter.
  • One authentication provider per MATTR VII tenant.

How it fits in the workflow:

  1. Holder initiates credential claim.
  2. MATTR VII redirects to your identity provider.
  3. Holder authenticates and consents.
  4. ID token claims become available for credential mapping.

Ensure the claims your credential configuration needs are available from your identity provider. Check the claims_supported and scopes_supported metadata at your provider's discovery endpoint. See ensuring claim availability.

Claims source

A claims source is an external HTTPS endpoint that MATTR VII calls during issuance to fetch additional claim data. This is useful when credential data lives in systems separate from your identity provider.

Common use cases:

  • Government databases (license records, registry data).
  • HR systems (employee attributes, role assignments).
  • CRM or customer databases (membership tiers, entitlements).

How it fits in the workflow:

  1. Holder authenticates (Authorization Code) or presents offer (Pre-authorized Code).
  2. MATTR VII calls your claims source endpoint with configured parameters.
  3. Your endpoint returns JSON claim data.
  4. Claims are mapped into the credential via the credential configuration.

Integration requirements:

  • HTTPS endpoint reachable from MATTR VII (IPv4).
  • Must respond within 3 seconds.
  • Supports API key or OAuth client credentials for authorization.
  • Must return claims as a flat or nested JSON object.

Interaction hooks

An interaction hook adds a custom step between authentication and credential issuance in the Authorization Code flow. This lets you inject additional verification, consent collection, or data gathering.

Common use cases:

  • Biometric or liveness verification.
  • Additional consent or terms acceptance.
  • Document upload or manual review steps.
  • Custom data collection forms.

How it fits in the workflow:

  1. Holder authenticates via the authentication provider.
  2. MATTR VII redirects to your interaction hook URL with a signed session token.
  3. Your component performs its logic (verification, consent, data collection).
  4. Your component redirects back to MATTR VII with a signed response JWT containing any claims.
  5. Returned claims become available for credential mapping.

Interaction hooks add latency and complexity. Use them only when the Authorization Code flow's built-in authentication is insufficient for your assurance requirements.

Manage issuer keys and certificates

Credentials must be signed with keys your organization controls. The signing certificate chain establishes trust—verifiers check that the credential was signed by a recognized issuer.

Key management options

OptionDescriptionUse case
MATTR managed KMS (SSM)Software-based key storage managed by MATTRDefault for most deployments
MATTR managed KMS (HSM)Hardware Security Module for key protectionHigh-assurance requirements
External KMSBring your own key management solutionOrganizations with existing PKI

Refer to the PKI spec sheet for detailed information on MATTR's key management capabilities.

Certificate chain of trust

For mDL issuance, your signing certificates must chain to an Issuing Authority Certificate Authority (IACA) root. This is the same root that verifiers check during presentation.

See the certificates overview and chain of trust concepts for detailed guidance.

Manage credential lifecycle

Once issued, credentials may need their status updated. MATTR VII supports revocation through published status lists.

Revocation

  • Configure revocation by enabling includeStatus in your credential configuration.
  • MATTR VII publishes a status list that verifiers can retrieve.
  • Control caching behavior with two parameters:
    • Time to Live (ttl) — recommended duration for using a retrieved copy of the status list before fetching the latest version. Defaults to one day.
    • Expiry (exp) — hard deadline after which a retrieved status list must not be used. Defaults to seven days.
  • Wallets and verifiers can rely on cached statuses between ttl and exp to maintain offline usability. Setting appropriate values balances up-to-date status checking with user experience.
  • Consider how to notify users if their credentials are revoked.

Monitoring with analytics

Track issuance activity using MATTR VII's Analytics API:

  • Monitor issuance volume and success rates.
  • Identify failures (timeout, claim source errors, authentication failures).
  • Set up webhooks for real-time event streaming to your monitoring tools.

See the analytics setup guide for configuration.

Frequently asked questions

What credential formats does MATTR VII support for issuance?

MATTR VII supports mDocs (aligned with ISO/IEC 18013-5) and CWT/Semantic CWT credential formats through OID4VCI. Direct issuance (API-based, no wallet interaction) is available for CWT credentials.

Which wallets can receive credentials issued by MATTR VII?

Any wallet that implements the OID4VCI specification can receive credentials. You can target specific wallets using custom URI schemes or claimed HTTPS links, or allow any compatible wallet using the standard scheme.

MATTR also provides its own holding solutions that are fully compatible with MATTR VII issuance:

  • MATTR Holder SDKs — embed credential holding capabilities directly into your own mobile application (iOS, Android, React Native).
  • MATTR GO — a ready-to-use wallet application for end users.

Do I need my own identity provider?

For the Authorization Code flow, yes — you need an OIDC-compliant identity provider. For the Pre-authorized Code flow, no — you authenticate users through your own means before creating the credential offer.

Can I issue credentials without user interaction?

Yes. The Pre-authorized Code flow supports silent issuance within existing app sessions. Your application creates the credential offer programmatically and the wallet claims it without requiring the user to authenticate again.

How do I populate credential data from my existing systems?

Use a claims source — an HTTPS endpoint that MATTR VII calls to fetch data from your backend systems. Claims are mapped into the credential via your credential configuration's claim mappings.

What happens if my claims source is unavailable?

If the claims source times out (>3 seconds) or returns a non-2xx response, issuance fails. Design your claims source for high availability and consider which claims are marked as required vs optional with defaultValue fallbacks.

Can I add custom verification steps before issuing?

Yes. Use an interaction hook in the Authorization Code flow to add biometric checks, consent flows, or other custom logic between authentication and issuance.

How do I revoke a credential after issuance?

Use the MATTR VII revocation API to update the credential's status. The updated status is reflected in the published status list that verifiers check. See credential revocation for details.

Can I issue multiple credentials in one flow?

Yes. A credential offer can reference multiple credential configurations, allowing the holder to claim several credentials in a single interaction.

What is the maximum validity period for an mDL?

mDL credentials have a maximum validity constraint of 427 days, enforced by the credential configuration. Plan your refresh or re-issuance strategy accordingly.

How would you rate this page?

Last updated on

On this page