Skip to content

Commit 9c11cc8

Browse files
committed
Early out failure on delegation verify if missing credentials from chain
1 parent b702c04 commit 9c11cc8

File tree

10 files changed

+147
-7
lines changed

10 files changed

+147
-7
lines changed

examples/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @docknetwork/sdk-examples
22

3+
## 0.21.14
4+
5+
### Patch Changes
6+
7+
- @docknetwork/credential-sdk@0.54.14
8+
39
## 0.21.13
410

511
### Patch Changes

examples/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@docknetwork/sdk-examples",
33
"private": true,
44
"type": "module",
5-
"version": "0.21.13",
5+
"version": "0.21.14",
66
"scripts": {
77
"bbs-dock-example": "babel-node ./src/bbs-dock.js",
88
"claim-deduction-example": "babel-node ./src/claim-deduction.js",
@@ -18,7 +18,7 @@
1818
"lint": "eslint \"src/**/*.js\""
1919
},
2020
"dependencies": {
21-
"@docknetwork/credential-sdk": "0.54.13",
21+
"@docknetwork/credential-sdk": "0.54.14",
2222
"@docknetwork/cheqd-blockchain-api": "4.0.7",
2323
"@docknetwork/cheqd-blockchain-modules": "4.0.8"
2424
},

packages/credential-sdk/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# @docknetwork/credential-sdk
22

3+
## 0.54.14
4+
5+
### Patch Changes
6+
7+
- Updated dependencies
8+
- @docknetwork/vc-delegation-engine@1.0.3
9+
310
## 0.54.13
411

512
### Patch Changes

packages/credential-sdk/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@docknetwork/credential-sdk",
3-
"version": "0.54.13",
3+
"version": "0.54.14",
44
"license": "MIT",
55
"type": "module",
66
"files": [
@@ -62,7 +62,7 @@
6262
"uuid": "^10.0.0",
6363
"uuidv4": "^6.2.13",
6464
"varint": "^6.0.0",
65-
"@docknetwork/vc-delegation-engine": "1.0.2"
65+
"@docknetwork/vc-delegation-engine": "1.0.3"
6666
},
6767
"devDependencies": {
6868
"@babel/cli": "^7.24.1",

packages/vc-delegation-engine/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @docknetwork/vc-delegation-engine
22

3+
## 1.0.3
4+
5+
### Patch Changes
6+
7+
- Early out failure on delegation verify if missing credentials from chain
8+
39
## 1.0.2
410

511
### Patch Changes

packages/vc-delegation-engine/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@docknetwork/vc-delegation-engine",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"description": "",
55
"main": "dist/cjs/index.cjs",
66
"module": "dist/esm/index.js",

packages/vc-delegation-engine/src/engine.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,30 @@ export async function verifyVPWithDelegation({
456456
skippedCredentials,
457457
};
458458
}
459+
460+
// Early out failure if missing credential from chain
461+
normalizedCredentials.forEach((credential) => {
462+
const { id, previousCredentialId, rootCredentialId } = credential;
463+
if (previousCredentialId && !normalizedById.has(previousCredentialId)) {
464+
throw new DelegationError(
465+
DelegationErrorCodes.MISSING_CREDENTIAL,
466+
`Missing credential ${previousCredentialId} referenced as previous by ${id}`,
467+
);
468+
}
469+
if (!rootCredentialId || typeof rootCredentialId !== 'string' || rootCredentialId.length === 0) {
470+
throw new DelegationError(
471+
DelegationErrorCodes.INVALID_CREDENTIAL,
472+
`Delegation credential ${id} is missing rootCredentialId`,
473+
);
474+
}
475+
if (!normalizedById.has(rootCredentialId)) {
476+
throw new DelegationError(
477+
DelegationErrorCodes.MISSING_CREDENTIAL,
478+
`Missing root credential ${rootCredentialId} referenced by ${id}`,
479+
);
480+
}
481+
});
482+
459483
const tailCredentials = normalizedCredentials.filter((vc) => !referencedPreviousIds.has(vc.id));
460484
if (tailCredentials.length === 0) {
461485
throw new DelegationError(

packages/vc-delegation-engine/tests/unit/engine.test.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
} from 'vitest';
44
import jsonld from 'jsonld';
55
import { verifyVPWithDelegation } from '../../src/engine.js';
6+
import { DelegationErrorCodes } from '../../src/errors.js';
67
import {
78
VC_TYPE,
89
VC_VC,
@@ -17,6 +18,8 @@ import {
1718

1819
const ROOT_CREDENTIAL_ID = 'urn:cred:root';
1920
const LEAF_CREDENTIAL_ID = 'urn:cred:leaf';
21+
const MISSING_PREVIOUS_ID = 'urn:cred:missing-prev';
22+
const UNKNOWN_ROOT_REFERENCE = 'urn:cred:missing-root';
2023
const W3C_CONTEXT = 'https://www.w3.org/2018/credentials/v1';
2124
const ISSUER_ROOT = 'did:root';
2225
const SUBJECT_DELEGATE = 'did:delegate';
@@ -124,6 +127,94 @@ describe('engine', () => {
124127
expect(result.decision).toBe('allow');
125128
expect(result.evaluations).toHaveLength(1);
126129
});
130+
131+
it('denies when a credential references a missing previous credential', async () => {
132+
const presentation = [
133+
{
134+
'@type': [VC_TYPE],
135+
[VC_VC]: [
136+
{
137+
'@graph': [
138+
{
139+
'@id': LEAF_CREDENTIAL_ID,
140+
'@type': [VC_TYPE_DELEGATION_CREDENTIAL],
141+
[VC_ISSUER]: [{ '@id': SUBJECT_DELEGATE }],
142+
[VC_SUBJECT]: [{ '@id': SUBJECT_HOLDER }],
143+
[VC_ROOT_CREDENTIAL_ID]: [{ '@id': LEAF_CREDENTIAL_ID }],
144+
[VC_PREVIOUS_CREDENTIAL_ID]: [{ '@id': MISSING_PREVIOUS_ID }],
145+
},
146+
],
147+
},
148+
],
149+
[SECURITY_PROOF]: [
150+
{
151+
[SECURITY_VERIFICATION_METHOD]: [{ '@id': `${SUBJECT_DELEGATE}#key` }],
152+
},
153+
],
154+
},
155+
];
156+
const contexts = new Map([[LEAF_CREDENTIAL_ID, [W3C_CONTEXT]]]);
157+
158+
const result = await verifyVPWithDelegation({
159+
expandedPresentation: presentation,
160+
credentialContexts: contexts,
161+
});
162+
163+
expect(result.decision).toBe('deny');
164+
expect(result.failures?.[0]?.code).toBe(DelegationErrorCodes.MISSING_CREDENTIAL);
165+
expect(result.failures?.[0]?.message).toContain(MISSING_PREVIOUS_ID);
166+
});
167+
168+
it('denies when a credential references a root credential that is not present', async () => {
169+
const presentation = [
170+
{
171+
'@type': [VC_TYPE],
172+
[VC_VC]: [
173+
{
174+
'@graph': [
175+
{
176+
'@id': ROOT_CREDENTIAL_ID,
177+
'@type': [VC_TYPE_DELEGATION_CREDENTIAL],
178+
[VC_ISSUER]: [{ '@id': ISSUER_ROOT }],
179+
[VC_SUBJECT]: [{ '@id': SUBJECT_DELEGATE }],
180+
[VC_ROOT_CREDENTIAL_ID]: [{ '@id': ROOT_CREDENTIAL_ID }],
181+
},
182+
],
183+
},
184+
{
185+
'@graph': [
186+
{
187+
'@id': LEAF_CREDENTIAL_ID,
188+
'@type': [VC_TYPE_DELEGATION_CREDENTIAL],
189+
[VC_ISSUER]: [{ '@id': SUBJECT_DELEGATE }],
190+
[VC_SUBJECT]: [{ '@id': SUBJECT_HOLDER }],
191+
[VC_ROOT_CREDENTIAL_ID]: [{ '@id': UNKNOWN_ROOT_REFERENCE }],
192+
[VC_PREVIOUS_CREDENTIAL_ID]: [{ '@id': ROOT_CREDENTIAL_ID }],
193+
},
194+
],
195+
},
196+
],
197+
[SECURITY_PROOF]: [
198+
{
199+
[SECURITY_VERIFICATION_METHOD]: [{ '@id': `${ISSUER_ROOT}#key` }],
200+
},
201+
],
202+
},
203+
];
204+
const contexts = new Map([
205+
[ROOT_CREDENTIAL_ID, [W3C_CONTEXT]],
206+
[LEAF_CREDENTIAL_ID, [W3C_CONTEXT]],
207+
]);
208+
209+
const result = await verifyVPWithDelegation({
210+
expandedPresentation: presentation,
211+
credentialContexts: contexts,
212+
});
213+
214+
expect(result.decision).toBe('deny');
215+
expect(result.failures?.[0]?.code).toBe(DelegationErrorCodes.MISSING_CREDENTIAL);
216+
expect(result.failures?.[0]?.message).toContain(UNKNOWN_ROOT_REFERENCE);
217+
});
127218
it('fails when credential contexts are missing', async () => {
128219
const result = await verifyVPWithDelegation({
129220
expandedPresentation: buildPresentation(),

scripts/bench/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @docknetwork/benchmarks
22

3+
## 0.4.14
4+
5+
### Patch Changes
6+
7+
- @docknetwork/credential-sdk@0.54.14
8+
39
## 0.4.13
410

511
### Patch Changes

scripts/bench/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
"name": "@docknetwork/benchmarks",
33
"private": true,
44
"type": "module",
5-
"version": "0.4.13",
5+
"version": "0.4.14",
66
"scripts": {
77
"bench": "babel-node src/main.js"
88
},
99
"dependencies": {
1010
"@docknetwork/cheqd-blockchain-api": "4.0.7",
1111
"@docknetwork/cheqd-blockchain-modules": "4.0.8",
12-
"@docknetwork/credential-sdk": "0.54.13",
12+
"@docknetwork/credential-sdk": "0.54.14",
1313
"@docknetwork/crypto-wasm-ts": "^0.63.0"
1414
},
1515
"devDependencies": {

0 commit comments

Comments
 (0)