Verifiable Credential Claim
The verifiableCredential
claim allows your application to request proof of an attribute, qualification, or ownership from a user. The user provides this proof by presenting a Verifiable Credential (VC) from their DID Wallet. This is a powerful mechanism for scenarios like proving identity, verifying ownership for gated access, or confirming personal information like an email address, without sharing the raw data itself.
How It Works#
The process involves the application specifying criteria for a credential, the user selecting a matching credential from their wallet, and the wallet returning it to the application inside a secure, verifiable presentation.
Parameters#
The verifiableCredential
claim can be configured with several parameters to specify the exact credential you need. The most flexible and recommended method is using the filters
array.
Parameter | Type | Description |
---|---|---|
|
| Required. Text displayed to the user in the wallet, explaining why the credential is being requested. |
|
| If |
|
| An array of filter objects. The wallet searches for credentials that match any of the filters (OR logic). This is the recommended approach for all new implementations. |
|
| A URL where the user can learn more about the credential being requested. Can be specified at the top level or within a filter. |
|
| A URL where the user can obtain the required credential if they don't have it. Can be specified at the top level or within a filter. |
Filter Object#
When using the filters
array, each object within the array defines a set of criteria. All criteria within a single filter object must be met (AND logic).
Parameter | Type | Description |
---|---|---|
|
| An array of acceptable VC type names (e.g., |
|
| An array of DIDs for issuers you trust. The credential must be issued by one of these DIDs. An issuer can be a DID string or an object |
|
| A specific string that may be present in the credential's metadata or subject, used for fine-grained filtering. For instance, for an email VC, this could be a digest of the email address. |
|
| The DID of the credential itself. |
|
| An array of DIDs. The owner of the credential must be one of these DIDs. |
Legacy Parameters#
For simple requests, you can use top-level parameters as a shorthand for a single filter. It is recommended to use the filters
array for clarity and future compatibility.
Parameter | Type | Description |
---|---|---|
|
| Alias for |
|
| Alias for |
|
| Alias for |
|
| Alias for |
|
| Alias for |
Example: Requesting a Specific Credential#
This example demonstrates how to request an EmailVerificationCredential
. It specifies the credential type, a list of trusted issuers, and a claimUrl
to provide more context to the user.
Requesting the Claim
This configuration is placed within your DID Connect handler.
// From an auth handler file, e.g., api/routes/auth/consume-vc.js
const joinUrl = require('url-join');
const env = require('../../libs/env');
const { wallet } = require('../../libs/auth');
// ... handler definition
{
action: 'consume_vc',
claims: {
verifiableCredential: async ({ userDid }) => {
const trustedIssuers = (env.trustedIssuers || []).concat(wallet.address);
return {
description: 'Please provide your Email Verification Credential',
item: ['EmailVerificationCredential'], // Using legacy 'item' for simplicity
trustedIssuers,
claimUrl: joinUrl(env.appUrl, '/claim/email'),
};
},
},
onAuth: async ({ userDid, claims, challenge }) => {
// Verification logic goes here, see below
},
}
Handling the Response
Once the user provides the credential, your onAuth
callback receives it within a verifiable presentation. You must parse and verify this presentation to ensure its authenticity and integrity.
// In the onAuth callback of the handler
const { verifyPresentation } = require('@arcblock/vc');
const vcClaim = claims.find(x => x.type === 'verifiableCredential');
if (!vcClaim || !vcClaim.presentation) {
throw new Error('Verifiable credential was not provided');
}
const presentation = JSON.parse(vcClaim.presentation);
// 1. Verify the challenge to prevent replay attacks
if (challenge !== presentation.challenge) {
throw Error('Invalid presentation: challenge mismatch');
}
// 2. Verify the presentation's signature and issuer trust
const trustedIssuers = (env.trustedIssuers || []).concat(wallet.address);
await verifyPresentation({ presentation, trustedIssuers, challenge });
// 3. (Optional) Perform business-specific checks on the credential content
const vc = JSON.parse(presentation.verifiableCredential[0]);
if (vc.type.indexOf('EmailVerificationCredential') === -1) {
throw Error('Incorrect credential type provided');
}
// Business logic passed
console.log('VC Verified Successfully!');
Example: Requesting One of Multiple Credential Types#
By using the filters
array, you can allow the user to provide any credential that matches one of several criteria. This is useful for granting access based on different qualifications, such as owning one of several possible NFTs.
Requesting the Claim
This example asks for either a BlockletPurchaseCredential
or a NodeOwnershipCredential
.
// From an auth handler file, e.g., api/routes/auth/verify-vc.js
{
action: 'verify-vc',
claims: {
verifiableCredential: () => {
return {
description: 'Please provide your blocklet or node NFT to continue',
filters: [
{
type: ['BlockletPurchaseCredential'],
trustedIssuers: [wallet.address],
tag: 'your-blocklet-did', // A specific identifier for the blocklet
},
{
type: ['NodeOwnershipCredential'],
trustedIssuers: [wallet.address],
tag: 'your-node-id', // A specific identifier for the node
},
],
};
},
},
onAuth: async ({ claims, challenge }) => {
// Verification logic
const presentation = JSON.parse(claims.find(x => x.type === 'verifiableCredential').presentation);
await verifyPresentation({ presentation, trustedIssuers: [wallet.address], challenge });
const vc = JSON.parse(presentation.verifiableCredential[0]);
if (vc.credentialSubject.isOwnerOf) {
console.log('Node ownership verified!');
} else if (vc.credentialSubject.purchased) {
console.log('Blocklet purchase verified!');
} else {
throw new Error('Presented credential is not valid for this scenario.');
}
},
}
In this case, the onAuth
logic needs to inspect the content (credentialSubject
) of the presented VC to determine which condition was met and proceed with the appropriate business logic.
Now that you understand how to request Verifiable Credentials, you may want to learn how to request on-chain items. Continue to the Asset Claim documentation for more details.