Present a Verifiable Credential
Receive and present a SD-JWT Verifiable Credential, signed by a did:cheqd Decentralized Identifier (DID), using Credo and OpenID4VP.
Using the OpenID4VC module, you can receive and present a OpenID compatible SD-JWT Credentials signed by a did:cheqd
identifier. This guide walks through the flow of presentation using the Credo Agent.
Prerequisites
Before you being, ensure you have:
Basic knowledge of Credo Agent configuration.
Step 1: Configure the Holder Agent
Configure the holder with cheqd and OpenID4VC Modules
import { Agent, DidsModule } from '@credo-ts/core';
import { agentDependencies } from '@credo-ts/node';
import { CheqdModule } from '@credo-ts/cheqd';
import { OpenId4VcHolderModule } from '@credo-ts/openid4vc';
const holder = new Agent({
config,
dependencies: agentDependencies,
modules: {
dids: new DidsModule({
resolvers: [new CheqdDidResolver()],
}),
openId4VcHolderModule: new OpenId4VcHolderModule(),
},
});
Step 2: Resolve and Accept Credential Offer
import { DidKey, KeyDidCreateOptions, getJwkFromKey } from '@credo-ts/core';
const resolved = await holder.modules.openId4VcHolder.resolveCredentialOffer(credentialOffer);
const credentials = await holder.modules.openId4VcHolder.acceptCredentialOfferUsingPreAuthorizedCode(
resolved,
{
credentialBindingResolver: async ({
supportedDidMethods,
keyType,
supportsAllDidMethods,
supportsJwk,
credentialFormat,
}) => {
if (supportsAllDidMethods || supportedDidMethods?.includes('did:key')) {
const didResult = await holder.dids.create<KeyDidCreateOptions>({
method: 'key',
options: { keyType },
});
const didKey = DidKey.fromDid(didResult.didState.did);
return {
method: 'did',
didUrl: `${didKey.did}#${didKey.key.fingerprint}`,
};
}
if (supportsJwk && credentialFormat === OpenId4VciCredentialFormatProfile.SdJwtVc) {
const key = await holder.wallet.createKey({ keyType });
return { method: 'jwk', getJwkFromKey(key) };
}
throw new Error('No binding method supported.');
},
}
);
This method:
Resolves the offer.
Accepts it via pre-authorized code flow.
Selects a binding method—
did:key
(preferred) or JWK—for the SD-JWT, depending on issuer capabilities
Step 3: Store the Credentials
// Store the received credentials
const records: Array<W3cCredentialRecord | SdJwtVcRecord> = []
for (const credential of credentials) {
if ('compact' in credential) {
const record = await holder.sdJwtVc.store(credential.compact)
records.push(record)
} else {
const record = await holder.w3cCredentials.storeCredential({
credential,
})
records.push(record)
}
}
Step 4: Resolve and Accept Authorization Request
Once you have a credential in your wallet, you can present it by responding to a receive authorization request, which includes an OpenID4VP presentation request. This request can be generated either by the verifier module or an external OpenID4VC verifier. First, resolve the authorization request, then accept it to present the credential in your wallet.
// resolved credential offer contains the offer, metadata, etc..
const resolvedRequest = await holder.modules.openId4VcHolderModule.resolveSiopAuthorizationRequest(authorizationRequest)
console.log(
'Resolved credentials for request', JSON.stringify(resolvedRequest.presentationExchange.credentialsForRequest, null, 2)
)
const presExchangeService = holder.dependencyManager.resolve(DifPresentationExchangeService)
// Automatically select credentials. In a wallet you could manually choose which credentials to return based on the "resolvedAuthorizationRequest.presentationExchange.credentialsForRequest" value
const selectedCredentials = presExchangeService.selectCredentialsForRequest(
resolvedRequest.presentationExchange.credentialsForRequest
)
// issuer only supports pre-authorized flow for now
const authorizationResponse = await holder.modules.openId4VcHolderModule.acceptSiopAuthorizationRequest({
authorizationRequest: resolvedRequest.authorizationRequest,
presentationExchange: {
credentials: selectedCredentials,
},
})
console.log('Submitted authorization response', JSON.stringify(authorizationResponse.submittedResponse, null, 2))
Last updated
Was this helpful?