Request a Verifiable Credential
Verifiable Credentials (VCs) are a core part of a decentralized identity ecosystem, allowing users to prove things about themselves—such as possessing a certificate, a license, or a badge—in a secure and verifiable way. This guide shows you how to request a specific VC from a user's wallet as part of your DID Connect flow.
This is accomplished using the verifiableCredential claim. For a detailed reference of all available properties, see the Claim Types API Reference.
How It Works#
The process of requesting and receiving a Verifiable Credential involves a conversation between your application and the user's wallet, facilitated by the DID Connect protocol.
Basic Request by Type#
The simplest way to request a credential is by its type. For instance, if you want to verify that a user has a BlockletServerPassport, you can specify it in the claims object.
// Inside handlers.attach configuration
{
// ... other options
claims: {
verifiableCredential: {
description: 'Please present your Blocklet Server Passport to continue.',
filters: [
{
type: ['BlockletServerPassport'],
},
],
optional: false, // Set to true if the credential is not strictly required
},
},
async onAuth(req, res) {
// The credential will be in the claims array
const passportClaim = req.didConnect.claims.find(
(x) => x.type === 'verifiableCredential'
);
if (passportClaim && passportClaim.vp) {
// The Verifiable Presentation (VP) is in the `vp` property
// You should now verify the VP and its containing VC
console.log('Received Passport:', passportClaim.vp);
}
res.json({ ok: 1, message: 'VC Received' });
},
}When the user scans the QR code, their wallet checks for any credential of the type BlockletServerPassport. If one or more are found, the user can select one to share with your application. The selected credential will be available in the onAuth callback as a Verifiable Presentation (vp) for you to verify.
Advanced Filtering#
You often need more specific criteria than just the type. The filters property allows you to construct more complex queries. filters is an array of filter objects where the wallet will find credentials that match any of the filter objects (an OR condition). Within a single filter object, all conditions must be met (an AND condition).
Here are the available properties for a filter object:
Property | Type | Description |
|---|---|---|
|
| An array of VC types. The credential must match one of the types. |
|
| An array of issuer DIDs. The credential must be issued by one of these DIDs. |
|
| The DID of the credential itself. Useful for requesting a very specific VC. |
|
| A specific tag that must be present on the credential. |
|
| A URL the wallet can show the user to learn more about the required credential. |
|
| A URL the wallet can direct the user to if they do not have the required credential, allowing them to obtain it. |
Example: Requesting a Credential with Multiple Criteria#
Let's say you want to grant access to users who either:
- Have a
BlockletServerPassportissued by a specific trusted authority. - OR have any credential with the tag
"trusted_developer".
You can configure your claim like this:
// Inside handlers.attach configuration
{
// ... other options
claims: {
verifiableCredential: {
description: 'Please present your server passport or developer credential.',
filters: [
{
type: ['BlockletServerPassport'],
trustedIssuers: ['zNKjDm4Xsoaffb19UE6QxVeevuaTaLCS1n1S'], // A specific trusted issuer DID
},
{
tag: 'trusted_developer',
},
],
},
},
async onAuth(req, res) {
const vcClaim = req.didConnect.claims.find(
(x) => x.type === 'verifiableCredential'
);
if (vcClaim && vcClaim.vp) {
// The Verifiable Presentation (VP) is in the `vp` property
// You should now verify the VP and its containing VC
console.log('Received Credential:', vcClaim.vp);
}
res.json({ ok: 1, message: 'Credential Received' });
},
}This configuration gives users a flexible way to prove their eligibility. They can satisfy either the first or the second condition to proceed.
Legacy Syntax#
Older versions of the protocol used a flatter structure without the filters array. While the current library maintains backward compatibility, you should use the filters array for all new implementations as it provides more flexibility.
An example using the legacy syntax:
// Legacy V1 - Use filters (V2) for new projects
{
claims: {
verifiableCredential: {
description: 'verifiable credential legacy',
item: ['BlockletServerPassport'], // Alias for `filters: [{ type: [...] }]`
trustedIssuers: ['zNKjDm4Xsoaffb19UE6QxVeevuaTaLCS1n1S'],
},
},
}Next Steps#
Now that you can request credentials, you might want to learn how to request other types of data or actions from the user's wallet.