Skip to main content
Version: v0.6.x

Migrating from Credo 0.5.x to 0.6.x

This document describes everything you need to know for updating Credo 0.5.x to 0.6.x. If you're not aware of how updating in Credo works make sure to first read the guide on Updating Credo.

First of all, update your dependencies to the 0.6.x versions. This will also update the needed peer dependencies. Extension packages are not updated with this command. You need to update these manually, and make sure they're up to date with the latest version of Credo.

Credo 0.6.0 is a major release with a large number of breaking changes. The most notable ones are:

  • ESM-only: Credo is now a pure ESM package. CommonJS require() is only supported in Node.JS 20.19 and above. But we recommend updating your project to ESM.
  • DIDComm extracted from core: All DIDComm-related functionality has been moved to the new @credo-ts/didcomm package.
  • New KMS API: The wallet API has been completely rewritten. agent.wallet is replaced by agent.kms.
  • Wallet config moved: walletConfig has been removed from the main agent config and moved to the Askar module's store property.
  • Askar dependency renamed: @hyperledger/aries-askar-* packages have been replaced by @openwallet-foundation/askar-*.
  • label and connectionImageUrl removed from agent configuration.
  • did:peer:4 is now the default for DID Exchange requests.
  • Node 18 deprecated: Node 20 and 22 are now the supported versions.

Follow the mentioned steps in this document carefully to make the upgrade as smooth as possible.

caution

The migration guide only covers how to migrate from 0.5.x to 0.6.x while keeping the same behavior and dependencies. There are many new features in 0.6.0 (Drizzle ORM storage, batch credentials, DCQL, W3C VCDM 2.0, etc.) that are not covered here. Refer to the release notes and the individual package changelogs for more information on new features.

caution

The automatic backup functionality has been removed from Credo 0.6.0. You are expected to create a backup yourself before performing any updates. For Askar you can export a store using the Askar API, or you can directly create a backup of your Postgres database.

First install the updated dependencies. For all dependencies you have in package.json, update them to the following versions, for your platform. If you don't use a package, you don't have to add it here.

In the upgrade from 0.5 to 0.6, there is a new @credo-ts/didcomm package that must be added if your application uses DIDComm. Also, the Askar native bindings have been moved from @hyperledger to @openwallet-foundation scope, so @hyperledger/aries-askar-* should be replaced by @openwallet-foundation/askar-*.

React Native

  • "@credo-ts/core": "^0.6.0"
  • "@credo-ts/didcomm": "^0.6.0" (new, required if using DIDComm)
  • "@credo-ts/askar": "^0.6.0"
  • "@credo-ts/anoncreds": "^0.6.0"
  • "@credo-ts/openid4vc": "^0.6.0"
  • "@credo-ts/react-native": "^0.6.0"
  • "@credo-ts/tenants": "^0.6.0"
  • "@credo-ts/cheqd": "^0.6.0"
  • "@credo-ts/indy-vdr": "^0.6.0"
  • "@openwallet-foundation/askar-react-native": "^0.4.0" (replaces @hyperledger/aries-askar-react-native)
  • "@hyperledger/anoncreds-react-native": "^0.2.4"
  • "@hyperledger/indy-vdr-react-native": "^0.2.2"

Node

  • "@credo-ts/core": "^0.6.0"
  • "@credo-ts/didcomm": "^0.6.0" (new, required if using DIDComm)
  • "@credo-ts/askar": "^0.6.0"
  • "@credo-ts/anoncreds": "^0.6.0"
  • "@credo-ts/openid4vc": "^0.6.0"
  • "@credo-ts/node": "^0.6.0"
  • "@credo-ts/tenants": "^0.6.0"
  • "@credo-ts/cheqd": "^0.6.0"
  • "@credo-ts/indy-vdr": "^0.6.0"
  • "@openwallet-foundation/askar-nodejs": "^0.4.0" (replaces @hyperledger/aries-askar-nodejs)
  • "@hyperledger/anoncreds-nodejs": "^0.2.4"
  • "@hyperledger/indy-vdr-nodejs": "^0.2.2"

Breaking Code Changes

This section will list all breaking changes made to the public API of Credo between version 0.5.x and 0.6.x.

info

If you have custom modules take into account there could be a lot more breaking changes that aren't documented here. We try to make sure that the biggest breaking changes to the internal API are also documented here, but it is possible some breaking changes are not documented here (feel free to open a pull request).

ESM-only package

Credo 0.6.0 is now a pure ESM package. It cannot be require()'d from CommonJS. Since Node 20.19 you may be able to require() ESM modules. However, we strongly recommend moving to ESM instead.

If your project is a Node.js application, you will need to migrate it to ESM or use a Node.js version that supports requiring ESM modules (Node.js 22+). The recommended approach is to migrate your project to ESM:

  1. Add "type": "module" to your package.json.
  2. Replace all require() / module.exports with import / export.
  3. Use only full relative file paths for imports: import x from './index.js' instead of import x from '.'.
  4. Use the node: protocol for Node.js built-in imports (e.g. import fs from 'node:fs').
  5. If using TypeScript, add "module": "node16" and "moduleResolution": "node16" to your tsconfig.json. You must use a .js extension in relative imports even though you're importing .ts files.
  6. Replace usages of __dirname and __filename with import.meta.dirname and import.meta.filename (Node.js 20.11+), or use import.meta.url with fileURLToPath.

If your project is a React Native application, this change should not impact you since React Native uses its own bundler (Metro) which handles ESM syntax.

tip

For a comprehensive guide on migrating a CommonJS project to ESM, see Pure ESM package by Sindre Sorhus.

Node 18 deprecated

Starting from Credo 0.6, Node 18 has been deprecated. The supported versions are Node 20 and 22. We aim to keep support for all LTS releases that are either Current, Active, or in Maintenance.

See the Release Schedule on the Node.js website for information on past and upcoming Node.js releases.

DIDComm extracted from Core

One of the most significant changes in Credo 0.6.0 is that all DIDComm-related functionality has been extracted from @credo-ts/core into a new @credo-ts/didcomm package. This means:

  • If your application does not use DIDComm at all, you simply need to remove DIDComm-related settings from your Agent configuration. No @credo-ts/didcomm dependency is needed.
  • If your application does use DIDComm, you need to add @credo-ts/didcomm to your dependencies and update your imports and agent setup.

The following subsections cover all the DIDComm-related breaking changes.

Agent setup with DIDComm

Previously, DIDComm modules (connections, credentials, proofs, mediation, etc.) were automatically included in the agent. Now you must explicitly include them using the getDefaultDidcommModules() helper, and settings like endpoints are passed through DIDComm module configuration instead of the main agent config.

0.5.x
import { Agent } from '@credo-ts/core'
import { agentDependencies } from '@credo-ts/node'
import { HttpInboundTransport, HttpOutboundTransport } from '@credo-ts/node'

const agent = new Agent({
config: {
label: 'My Agent',
endpoints: ['https://myendpoint.com'],
walletConfig: {
id: 'my-wallet',
key: 'my-wallet-key',
},
},
dependencies: agentDependencies,
modules: {
/* ... other modules */
},
})

agent.registerInboundTransport(new HttpInboundTransport({ port: 3000 }))
agent.registerOutboundTransport(new HttpOutboundTransport())
0.6.x
import { Agent } from '@credo-ts/core'
import { agentDependencies } from '@credo-ts/node'
import {
getDefaultDidcommModules,
DidCommHttpInboundTransport,
DidCommHttpOutboundTransport,
} from '@credo-ts/didcomm'

const agent = new Agent({
config: {
// label and endpoints have been removed from config
},
dependencies: agentDependencies,
modules: {
...getDefaultDidcommModules({
endpoints: ['https://myendpoint.com'],
}),
/* ... other modules */
},
})

agent.didcomm.registerInboundTransport(new DidCommHttpInboundTransport({ port: 3000 }))
agent.didcomm.registerOutboundTransport(new DidCommHttpOutboundTransport())

DIDComm API access pattern

All DIDComm-related module APIs are now scoped under agent.didcomm instead of being accessed directly on agent.

0.5.x
const defaultMediator = await agent.mediationRecipient.findDefaultMediator()
const proofRecord = await agent.proofs.getById(proofRecordId)
const credentialRecord = await agent.credentials.getById(credentialRecordId)
const oobRecord = await agent.oob.createInvitation()
const connections = await agent.connections.getAll()
0.6.x
const defaultMediator = await agent.didcomm.mediationRecipient.findDefaultMediator()
const proofRecord = await agent.didcomm.proofs.getById(proofRecordId)
const credentialRecord = await agent.didcomm.credentials.getById(credentialRecordId)
const oobRecord = await agent.didcomm.oob.createInvitation()
const connections = await agent.didcomm.connections.getAll()

DIDComm class prefix changes

Most DIDComm-related classes, events and services now use the DidComm prefix in their naming. Imports must be updated from @credo-ts/core to @credo-ts/didcomm.

0.5.x
import {
AgentMessage,
ConnectionsModule,
MediatorPickupStrategy,
HttpInboundTransport,
HttpOutboundTransport,
WsInboundTransport,
WsOutboundTransport,
ConnectionEventTypes,
CredentialEventTypes,
ProofEventTypes,
} from '@credo-ts/core'
0.6.x
import {
DidCommMessage,
DidCommConnectionsModule,
DidCommMediatorPickupStrategy,
DidCommHttpInboundTransport,
DidCommHttpOutboundTransport,
DidCommWsInboundTransport,
DidCommWsOutboundTransport,
DidCommConnectionEventTypes,
DidCommCredentialEventTypes,
DidCommProofEventTypes,
} from '@credo-ts/didcomm'

DIDComm-related event type strings have also changed to distinguish them from events triggered by other protocols.

Credentials / Proofs API normalization

The DIDComm credentials and proofs APIs have been updated for consistency. In particular, credentialExchangeRecord is now used instead of credentialRecord and proofExchangeRecord instead of proofRecord in method parameters.

0.5.x
const requestedCredentials = await agent.proofs.selectCredentialsForRequest({
proofRecordId: proofRecord.id,
})

await agent.proofs.acceptRequest({
proofRecordId: proofRecord.id,
proofFormats: { anoncreds: requestedCredentials.proofFormats.anoncreds },
})
0.6.x
const requestedCredentials = await agent.didcomm.proofs.selectCredentialsForRequest({
proofExchangeRecordId: proofRecord.id,
})

await agent.didcomm.proofs.acceptRequest({
proofExchangeRecordId: proofRecord.id,
proofFormats: { anoncreds: requestedCredentials.proofFormats.anoncreds },
})

Dropped label and connectionImageUrl from agent configuration

The label and connectionImageUrl fields have been removed from the main Agent configuration. They are not present as a general DIDComm configuration parameter either. If you need to use them, you can specify them per-call in DIDComm connection establishment methods:

const outOfBandRecord = await agent.didcomm.oob.createInvitation({
label: 'My Agent',
imageUrl: 'https://myhost/myimage.png',
})

await agent.didcomm.oob.receiveInvitation(invitation, {
label: 'My Agent',
imageUrl: 'https://myhost/myimage.png',
})
tip

If you need to persist these values and your only persistent storage is the agent's wallet, you can use Generic Records to store arbitrary data.

DID Exchange defaults changed to did:peer:4

Up to Credo 0.5.x, the default did:peer method used for DID Exchange was did:peer:1. In 0.6.0, the default is now did:peer:4. If you are interacting with older agents that don't support this method, you can override this setting in the DIDComm connections module configuration:

import { DidCommConnectionsModule, PeerDidNumAlgo } from '@credo-ts/didcomm'

const agent = new Agent({
modules: {
...getDefaultDidcommModules({ endpoints: ['https://myendpoint.com'] }),
connections: new DidCommConnectionsModule({
peerNumAlgoForDidExchangeRequests: PeerDidNumAlgo.GenesisDoc,
}),
},
})

Inbound/Outbound transports configuration

Transports are now registered through the agent.didcomm API or as part of the DIDComm module configuration, instead of on the agent instance directly.

0.5.x
import { HttpInboundTransport, HttpOutboundTransport } from '@credo-ts/node'

agent.registerInboundTransport(new HttpInboundTransport({ port: 3000 }))
agent.registerOutboundTransport(new HttpOutboundTransport())
0.6.x
import {
DidCommHttpInboundTransport,
DidCommHttpOutboundTransport,
} from '@credo-ts/didcomm'

// Option 1: Register transports after agent creation
agent.didcomm.registerInboundTransport(new DidCommHttpInboundTransport({ port: 3000 }))
agent.didcomm.registerOutboundTransport(new DidCommHttpOutboundTransport())

Alternatively, transports can be specified directly in the DidCommModule configuration through the transports property, which is especially useful in React Native apps or when you want to keep all configuration in one place:

import {
DidCommModule,
DidCommHttpInboundTransport,
DidCommHttpOutboundTransport,
} from '@credo-ts/didcomm'

const agent = new Agent({
modules: {
didcomm: new DidCommModule({
transports: {
inbound: [new DidCommHttpInboundTransport({ port: 3000 })],
outbound: [new DidCommHttpOutboundTransport()],
},
}),
},
})

MessagePickupRepository → QueueTransportRepository

If you are creating a DIDComm mediator or a related extension module, MessagePickupRepository has been refactored to QueueTransportRepository and now belongs to DIDComm module configuration. The MessagePickupRepository injection symbol has been dropped. To retrieve the current QueueTransportRepository instance, resolve DidCommModuleConfig and access queueTransportRepository.

All methods in QueueTransportRepository now include AgentContext as their first argument.

Deprecated DIDComm protocols

The following DIDComm protocols are marked as deprecated in 0.6.0 and will be removed in version 0.7:

  • Connection Protocol V1 — Update to the DID Exchange protocol instead.
  • V1 Credential Protocol — Update to the V2 Credential Protocol instead.
  • Legacy Indy Credential Format — Update to the AnonCreds Credential Format.
  • V1 Proof Protocol — Update to the V2 Proof Protocol instead.
  • Legacy Indy Proof Format — Update to the AnonCreds Proof Format.

Express v5

If you're using the DIDComm HTTP transports or the OpenID4VC issuer/verifier packages, you should update to Express v5 (express@^5.0.0).

Wallet configuration removed from agent config

The walletConfig property has been removed from the main InitConfig. Instead, each module defines its own storage and KMS configuration. For Askar, there is a new store property on the AskarModule config where you set the wallet id and key.

0.5.x
import { Agent } from '@credo-ts/core'
import { AskarModule } from '@credo-ts/askar'
import { ariesAskar } from '@hyperledger/aries-askar-nodejs'

const agent = new Agent({
config: {
label: 'My Agent',
walletConfig: {
id: 'my-wallet',
key: 'my-wallet-key',
},
},
modules: {
askar: new AskarModule({ ariesAskar }),
},
})
0.6.x
import { Agent } from '@credo-ts/core'
import { AskarModule } from '@credo-ts/askar'
import { askar } from '@openwallet-foundation/askar-nodejs'

const agent = new Agent({
config: {
// walletConfig removed from here
},
modules: {
askar: new AskarModule({
askar,
store: {
id: 'my-wallet',
key: 'my-wallet-key',
},
}),
},
})

New Key Management System (KMS)

The wallet API has been completely rewritten. The previous agent.wallet API is replaced by the new agent.kms API. This new KMS supports multiple backends, symmetric keys, generic encryption/decryption, and identifies keys by key ID rather than by public key.

Key changes:

  • Key and Jwk classes removed — replaced by the new PublicJwk class.
  • JwaSignatureAlgorithm renamed — use Kms.KnownJwaSignatureAlgorithms instead.
  • agent.wallet removed — use agent.kms for all key management operations.
  • Wallet injection symbol removed — if you used this in custom modules, inject the KMS API using agentContext.resolve(Kms.KeyManagementApi) instead.
0.5.x
import { JwaSignatureAlgorithm, KeyType } from '@credo-ts/core'

const key = await agent.wallet.createKey({ keyType: KeyType.Ed25519 })
const publicKeyBase58 = key.publicKeyBase58
const algorithm = JwaSignatureAlgorithm.EdDSA
0.6.x
import { Kms } from '@credo-ts/core'

const { keyId, publicJwk } = await agent.kms.createKey({ type: 'ed25519' })
const algorithm = Kms.KnownJwaSignatureAlgorithms.EdDSA

DID signing requires DidRecord

When signing with DIDs in Credo, it is now required that all DIDs have an associated DidRecord with the created role. The new KMS API needs to track key IDs for keys within a DID document, and these are stored on the DID record. You can import a DID using agent.dids.import and provide the keys array to define the mapping between verification method and key ID. If a verification method mapping is not provided, Credo assumes the legacy key ID format (base58 encoded public key).

Credential record changes

Credential records have been updated to support batch credentials and KMS key tracking.

  • record.credential is now record.firstCredential
  • storeCredential() has been replaced by store() which expects a record parameter
0.5.x
await agent.w3cCredentials.storeCredential({ credential })

const credential = record.credential
0.6.x
const record = W3cCredentialRecord.fromCredential(credential)
await agent.w3cCredentials.store({ record })

const credential = record.firstCredential

Records now support multiple credential instances via the credentialInstances array and a multiInstanceState property to track usage.

Askar dependency renamed

The Askar native bindings have been moved from @hyperledger to @openwallet-foundation scope.

0.5.x
import { ariesAskar } from '@hyperledger/aries-askar-nodejs'
// or
import { ariesAskar } from '@hyperledger/aries-askar-react-native'
0.6.x
import { askar } from '@openwallet-foundation/askar-nodejs'
// or
import { askar } from '@openwallet-foundation/askar-react-native'

SD-JWT VC typ header default changed

The default typ header for SD-JWT VCs has been changed from vc+sd-jwt to dc+sd-jwt. You can still use vc+sd-jwt by providing the headerType value when signing an SD-JWT VC. For OID4VCI, the typ header is based on the OID4VCI credential format used.

BBS+ signatures removed

The BBS+ module has been removed. The underlying implementation was outdated and unmaintained. A new version based on the BBS standard currently being developed may be added in the future. If you still need the legacy BBS+ functionality, you can extract the code from an older commit of the Credo repository and create your own custom module.

Linked attachments removed

Support for DIDComm linked attachments has been removed. The functionality was not working correctly and only supported the deprecated V1 issuance protocol.

Indy SDK migration package removed

The @credo-ts/indy-sdk-to-askar-migration package has been removed. The Indy SDK has been deprecated for a long time, and all wallets should have been migrated to Askar by now. If you haven't migrated yet, first update to 0.5.x and then to 0.6.x.

Backup functionality removed

The automatic backup functionality has been removed from Credo. With the generalization of the KMS API and moving away from assuming Askar is used for storage, providing a generic backup API is not feasible. From now on, you are expected to create backups yourself before performing any updates.

Other notable changes

  • TypeScript target updated to ES2020 — this generally should not impact supported environments (Node.js / React Native).
  • Uint8Array instead of Buffer — internal key bytes representation now uses Uint8Array instead of Buffer.
  • Uncompressed keys by default — EC keys (P-256, P-384, P-521, K-256) now default to uncompressed representation.
  • Zod 4 — Credo has been updated to Zod 4. Although the public API has not changed, error messages and some error structures may differ.
  • DidCommV2Service renamedDidCommV2Service is now LegacyDidCommV2Service, and NewDidCommV2Service became the default DidCommV2Service.
  • Modules no longer experimentalDcqlModule, DifPresentationExchangeModule, SdJwtVcModule, MdocModule, TenantsModule, CheqdModule, DrpcModule, OpenId4VcModule, and X509Module are no longer experimental.
  • createDeviceResponse returns bytescreateDeviceResponse now returns raw Uint8Array bytes instead of a base64-encoded string.
  • DidDocumentService.protocolScheme() removed — this method has been removed as it's not possible to determine the protocol scheme from the base class.

X509 Certificate API changes

The X509Certificate API has been updated to better support key management:

  • The async getData() method has been split into a sync .data getter and an async getThumbprint() method.
  • APIs that involve signing now require X509Certificate instances instead of encoded certificate strings. This allows you to attach a keyId to the certificate before passing it.

When signing with an X509 certificate, a keyId must always be set on the certificate instance. For certificates created before 0.6, use the legacy key id format. For certificates created after 0.6, you must manually store the key id and re-attach it after decoding.

// For certificates created before 0.6
const certificate = X509Certificate.fromEncodedCertificate(encodedCert)
certificate.keyId = certificate.publicJwk.legacyKeyId

// For certificates created after 0.6 (store the keyId yourself)
const certificate = X509Certificate.fromEncodedCertificate(encodedCert)
certificate.keyId = myStoredKeyId

Self-signed certificate creation is now done via agent.x509.createCertificate where the subjectPublicKey is not supplied or is equal to the authorityKey.

OpenID4VC Module consolidation

The three separate OpenID4VC modules have been merged into a single OpenId4VcModule. The old OpenId4VcHolderModule, OpenId4VcIssuerModule, and OpenId4VcVerifierModule are replaced by OpenId4VcModule, which accepts optional issuer and verifier configuration. The holder is always available.

The router property on OpenId4VcIssuerModule and OpenId4VcVerifierModule has been replaced by a top-level app property on OpenId4VcModule. You pass your Express app instance directly, and Credo registers all routes (including .well-known paths) on it. If no app is provided and either issuer or verifier is configured, a new Express app instance is created automatically.

caution

Register your custom routes after calling agent.initialize() to ensure Credo's routes are registered first and your custom middleware does not clash with Credo's routes.

0.5.x
import express from 'express'
import { OpenId4VcHolderModule, OpenId4VcIssuerModule, OpenId4VcVerifierModule } from '@credo-ts/openid4vc'

const issuerApp = express()
const verifierApp = express()

const agent = new Agent({
modules: {
openId4VcHolder: new OpenId4VcHolderModule(),
openId4VcIssuer: new OpenId4VcIssuerModule({
baseUrl: 'https://issuer.example.com',
router: issuerRouter,
credentialRequestToCredentialMapper: async ({ credentialRequest }) => { /* ... */ },
}),
openId4VcVerifier: new OpenId4VcVerifierModule({
baseUrl: 'https://verifier.example.com',
router: verifierRouter,
}),
},
})

// Register routers manually
issuerApp.use('/oid4vci', issuerRouter)
verifierApp.use('/oid4vp', verifierRouter)

// Access holder API
await agent.modules.openId4VcHolder.resolveCredentialOffer(credentialOffer)
// Access issuer API
await agent.modules.openId4VcIssuer.createIssuer()
// Access verifier API
await agent.modules.openId4VcVerifier.createVerifier()
0.6.x
import express from 'express'
import { OpenId4VcModule } from '@credo-ts/openid4vc'

const app = express()

const agent = new Agent({
modules: {
openid4vc: new OpenId4VcModule({
app,
issuer: {
baseUrl: 'https://issuer.example.com',
credentialRequestToCredentialMapper: async ({ credentialRequest }) => { /* ... */ },
},
verifier: {
baseUrl: 'https://verifier.example.com',
},
}),
},
})

// Holder is always available
await agent.openid4vc.holder.resolveCredentialOffer(credentialOffer)
// Issuer API (only available if issuer config was provided)
await agent.openid4vc.issuer.createIssuer()
// Verifier API (only available if verifier config was provided)
await agent.openid4vc.verifier.createVerifier()

OpenID4VCI requestCredentials returns credential records

The requestCredentials method on the holder now returns objects with a record property (a W3cCredentialRecord, SdJwtVcRecord, or MdocRecord), pre-populated with KMS key IDs. Store each received credential using the store({ record }) method on the appropriate credential API.

0.5.x
const credentialsResult = await agent.modules.openId4VcHolder.requestCredentials({
resolvedCredentialOffer,
...accessTokenResponse,
credentialBindingResolver: () => ({ method: 'did', didUrls: [holderDid] }),
})

for (const credential of credentialsResult.credentials) {
await agent.w3cCredentials.storeCredential({ credential: credential.credential })
}
0.6.x
const credentialsResult = await agent.openid4vc.holder.requestCredentials({
resolvedCredentialOffer,
...accessTokenResponse,
credentialBindingResolver: () => ({ method: 'did', didUrls: [holderDid] }),
})

for (const credential of credentialsResult.credentials) {
if (credential.record instanceof W3cCredentialRecord) {
await agent.w3cCredentials.store({ record: credential.record })
} else if (credential.record instanceof SdJwtVcRecord) {
await agent.sdJwtVc.store({ record: credential.record })
} else if (credential.record instanceof MdocRecord) {
await agent.mdoc.store({ record: credential.record })
}
}

OpenID4VCI credential binding resolver called once

The credentialBindingResolver is now called once for the entire credential request (instead of once per credential). It can return multiple keys or a single key attestation to support batch issuance scenarios.

OpenID4VCI resolveIssuanceAuthorizationRequest renamed

The method for resolving an authorization code flow request has been renamed:

0.5.x
await agent.modules.openId4VcHolder.resolveIssuanceAuthorizationRequest(
resolvedCredentialOffer,
authCodeFlowOptions
)
0.6.x
await agent.openid4vc.holder.resolveOpenId4VciAuthorizationRequest(
resolvedCredentialOffer,
authCodeFlowOptions
)

OpenID4VCI draft version strings renamed

The version strings for credential offer versions have been updated. Draft 15 is incompatible with previous drafts, so if you are interacting with older issuers or holders you need to keep this in mind.

0.5.x0.6.x
v1.draft11-13v1.draft11-15
v1.draft13v1.draft15

V1 support has also been added (v1) which is the default.

SIOPv2 removed, renamed to OpenID4VP

Support for SIOPv2 has been removed. All classes, interfaces, and services that had Siop in their name have been renamed to use OpenId4Vp. For example, OpenId4VcSiopHolderService is now OpenId4VpHolderService. Update all imports accordingly.

OpenID4VP responseMode default changed to direct_post.jwt

The default responseMode when creating an authorization request has changed from direct_post (unencrypted) to direct_post.jwt (encrypted). If you need to revert to unencrypted responses (e.g., for interoperability with older agents), you can set the responseMode explicitly:

await agent.openid4vc.verifier.createAuthorizationRequest({
verifierId,
requestSigner: { /* ... */ },
presentationExchange: { /* ... */ },
responseMode: 'direct_post', // opt out of encryption
})

OpenID4VP DIF Presentation Exchange credential entry typeclaimFormat

The field in returned credential entries from DIF Presentation Exchange results has been renamed from type to claimFormat to better align with the DC API terminology.

0.5.x
const verifiedResponse = await agent.modules.openId4VcVerifier.verifyAuthorizationResponse({ /* ... */ })

for (const submission of verifiedResponse.presentationExchange.presentations) {
console.log(submission.type) // e.g. 'dc+sd-jwt'
}
0.6.x
const verifiedResponse = await agent.openid4vc.verifier.verifyAuthorizationResponse({ /* ... */ })

for (const submission of verifiedResponse.presentationExchange.presentations) {
console.log(submission.claimFormat) // e.g. 'dc+sd-jwt'
}

OpenID4VP DCQL multiple presentations per query

DCQL query results have changed: the selected credentials per query are now an array of credential IDs (at least one entry) instead of a single presentation. This allows the multiple option in DCQL queries to be properly supported.

OpenID4VP mDOC: only one document per device response

Per ISO 18013-7, only one mDOC document per OpenID4VP device response is now supported. If a device response contains multiple documents, each is verified separately. When creating a device response for OpenID4VP presentation, ensure you only include one document.

OpenID4VP x509_san_uri client id scheme removed on verifier side

Support for creating authorization requests using the x509_san_uri client id scheme has been removed from the verifier/issuer side (the holder still supports receiving such requests). This scheme is replaced by x509_hash in newer drafts, which is supported via the x509_hash client id prefix.

Additional Resources