Skip to main content
Version: v0.25.0 (Latest)

OpenID for Verifiable Credential Issuance (OpenID4VCI)

The IDK implements the OpenID4VCI issuer: metadata, credential offers, wallet-facing protocol handlers for /credential, /credential_deferred, /nonce, /notification, the DI graph wiring, and in-memory stores for a self-contained issuer. The protocol primitives and basic handler extension points remain in the IDK OpenID4VCI issuer guide.

The EDK adds the enterprise issuance runtime around that protocol. The issuer gets claim values through a connector-native PipelineConfiguration: automatic integration is expressed as ConnectorInvocationBinding records bound to named OID4VCI lifecycle stages. A binding can enrich fields, export selected data, write evidence to a vault, send notifications, or orchestrate a connector route. The session has an encrypted attribute bag and connector-field map; the pipeline contract is connector invocation bindings, not a parallel source model.

Choosing the credential and login flow

The protocol flow and the credential wire format are separate choices. An issuer can expose both of these formats, but each credential configuration must declare its own format, claims, signing material, and status policy:

Customer choiceEDK configuration boundaryWhat the wallet does
IETF SD-JWT VCformat: "dc+sd-jwt" and a vct valueRequests a selectively disclosable JWT credential and later discloses the selected claims
ISO/IEC 18013-5 mDocformat: "mso_mdoc" and a docType value such as org.iso.18013.5.1.mDLRequests an mdoc, performs mdoc device engagement/device authentication, and presents namespace-qualified elements

For issuance, use pre-authorized code when the issuer or an upstream business process can create an offer before the wallet user authenticates. Add a transaction code (tx_code) when a second channel must approve the token exchange. Use authorization code when the holder must authenticate first. With an external Keycloak OIDC provider, the issuer follows discovery, authorization-code, state/nonce, and PKCE validation; the pipeline then maps approved ID-token or UserInfo claims into connector fields and credential claims. Do not put Keycloak secrets or raw ID tokens into a credential design.

The admin/backend API creates and observes the pipeline session; the wallet-facing OID4VCI endpoints execute the protocol exchange. A successful offer or session response is not evidence that a wallet stored a credential, and an API-created mdoc configuration is not by itself evidence of mdoc issuer/device authentication.

For a production mdoc lane, configure the issuer signing key and the DSC/IACA chain expected by the relying-party ecosystem, then validate with a real mdoc-capable wallet. See Keys and DID, the authorization-code guide, and Verify credentials.

Issuer walkthrough surface

The public issuer testing-console route is useful for checking the configured credential types, issuance templates, discovery metadata, and session counts before a wallet walkthrough. The following screenshot is an illustrative example; use the URL and Open in Admin Console action exposed by your deployment rather than copying its identifiers.

Issuer testing console example

Captured offer requests

These local captures show the request shape for a pre-authorized SD-JWT VC, an ISO mDoc, and an authorization-code offer. Values are synthetic and safe to reuse as documentation fixtures; replace identifiers and claims for your own tenant.

Create EuPid offer

Endpoint: POST /api/oid4vci/v1/backend/credential/offers

Captured response: 201 Created

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.

Create Mdl offer

Endpoint: POST /api/oid4vci/v1/backend/credential/offers

Captured response: 201 Created

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.

Create offer with authorization code grant

Endpoint: POST /api/oid4vci/v1/backend/credential/offers

Captured response: 201 Created

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.

The Mental Model

An EDK issuance is an IssuancePipelineSession. The session carries:

  • an attribute bag: resolved fields that can become credential claims,
  • connector fields: correlation and integration inputs such as email, employee_id, identity_id, AS claims, or callback handles,
  • protocol status: where the session is in issuance, deferral, approval, and completion.

The session passes through OID4VCI phases. Connector invocations can run before or during offer creation, authorization, pre-authorized issuance, token exchange, credential request, pre-issue, deferred polling, post-issuance, and notification receipt. Each invocation sees the accumulated fields and can add fields for later phases.

When the wallet calls /credential, the EDK runs the credential-request and pre-issue connector phases, assembles claims from the bag, and hands the result to the IDK protocol handler to sign. If required data is not available synchronously, the wallet can receive a deferred response; later connector or callback work can complete the session before /credential_deferred returns the credential.

What the EDK Adds

A registered PipelineConfiguration per issuance flow. It declares invocationBindings, credential bindings, and expected initial connector fields. See Attribute Pipeline.

Connector invocation bindings. A binding connects an OID4VCI stage to a connector route, connector instance, or operation binding. It carries role, exchange mode, subset mapping, execution policy, logical context, governance metadata, Party anchors, and materialization policy. See Connector Invocations.

Pipeline session management endpoints. The EDK adds REST endpoints under /oid4vci/sessions/... for creating sessions, manually contributing attributes, evaluating completeness, approving issuance, failing an integration, and reading accumulated state. These endpoints are operator/backend surfaces; the wallet-facing OID4VCI endpoints remain protocol endpoints. See REST API.

Manual contribution surfaces. POST /api/oid4vci/v1/backend/sessions/{correlationId}/attributes and POST /api/oid4vci/v1/backend/credential/offers can push data into the session using compact groups. In those request bodies, contributorId is record provenance for manually supplied data. It is not the automatic integration contract; automatic runtime integration uses PipelineConfiguration.invocationBindings.

Async and deferred execution. Connector execution policies can be inline, optional, deferred async, or durable outbox. The EDK can hold /credential open for a configured sync window and fall through to deferred issuance when an integration cannot complete in time. Callback ingress is still secured by an opaque capability token scoped to one session and contribution.

Deferral and approval gates. Each credential binding carries deferral and approval policy. AWAITING_DEFERRED and AWAITING_APPROVAL are observable separately from the protocol-level deferred credential response.

Encrypted session persistence. Sessions carry sensitive data. The EDK provides plaintext mode for development, platform-encrypted mode under a tenant KEK, and client-bound mode tied to the session correlation id. See Persistence.

Tenant-aware issuer paths. Protocol endpoints can optionally be reached through a tenant slug path, while host-based tenant resolution continues to work.

Explicit authorization-server selection. An issuer binds one or more tenant authorization-server resources by stable UUID and has exactly one enabled default. An issuance-template override takes precedence over a credential-configuration override, which takes precedence over the issuer default. Each layer has its own grant allowlist. The resolved UUID is translated to the server's issuer URL only when OID4VCI metadata or an authorization request is produced. Issuer metadata lists every enabled bound issuer identifier in authorization_servers. The standard grant-level authorization_server appears only when several servers are advertised, and credential metadata does not receive a non-standard per-credential property. An external OAuth2-only server is valid for issuance when fresh discovery advertises the required grant; OIDC is required only for hosted-login federation. See Authorization servers and protocol profile.

Explicit protocol profiles. Each issuer stores its OID4VCI protocol profile. New issuers use OID4VCI_1_0_FINAL; the governed preview is OID4VCI_1_1_DRAFT_2A1F0513. A profile change starts with a dry-run that checks credentials, metadata, grants, authorization-server bindings, and templates. Apply is revision guarded and never follows a changed global default silently. In-flight offers and authorization transactions retain the profile snapshot recorded when they started.

How a Developer Builds an Issuer

  1. Define credential designs. The credential design system is the source of truth for credential configurations, claim policy, status lists, and display/render data.

  2. Register connector invocation bindings for the stages where issuance needs integration. A typical employee credential pipeline might bind OID4VCI_START for audit, OID4VCI_AUTHORIZATION for authenticated-user context, OID4VCI_TOKEN to resolve an external identifier, OID4VCI_CREDENTIAL_REQUEST to fetch the HR record, OID4VCI_PRE_ISSUE for final enrichment or policy state, and OID4VCI_POST_ISSUANCE for vault retention.

  3. Register the PipelineConfiguration with invocationBindings, credential bindings, and expected initial connector fields.

  4. Bind the authorization servers the issuer may use, choose one enabled default, and add credential or template overrides only where the default is not appropriate. Validate that every selected server supports the layer's allowed grants.

  5. Dry-run any protocol-profile upgrade and resolve every blocking compatibility issue before applying it.

  6. Let the IDK/EDK protocol handlers run the phases at the correct OID4VCI moments. You only call the pipeline REST API when backend code needs to seed, observe, approve, or manually contribute to a session.

You write code only when you need a new connector implementation, a custom route executor, or a custom claim mapper.

Where Things Live

ConcernModule
Issuer protocol service, DSL, handlerscom.sphereon.idk:lib-openid-oid4vci-issuer-public / -impl
Issuer REST endpointscom.sphereon.idk:services-oid4vci-issuer-rest plus EDK tenant adapters
Pipeline session and command typescom.sphereon.edk:lib-credential-issuance-pipeline-public
Attribute bag and phase typescom.sphereon.idk:lib-attribute-flow-public
Connector invocation contractscom.sphereon.edk:lib-connector-public
Pipeline command implementations and OID4VCI connector bridgecom.sphereon.edk:lib-credential-issuance-pipeline-impl
VDX durable connector registry, routes, grants, throttling, run lineage, and invocation binding REST/admin surfacecom.sphereon.vdx:vdx-data-store-connector-*
Tenant-aware path adaptercom.sphereon.edk:lib-openid-oid4vci-issuer-rest-tenant
Service contractscom.sphereon.edk:lib-openid-oid4vci-issuer-contract
Deployable containercom.sphereon.edk:services-oid4vci-issuer

Next Steps