diff --git a/lib/di.js b/lib/di.js index 4e22d7a..78fac20 100644 --- a/lib/di.js +++ b/lib/di.js @@ -2,7 +2,7 @@ * Copyright (c) 2018-2024 Digital Bazaar, Inc. All rights reserved. */ import * as vc from '@digitalbazaar/vc'; -import {checkStatus} from './status.js'; +import {checkStatus as _checkStatus} from './status.js'; import {createDocumentLoader} from './documentLoader.js'; import {createSuites} from './suites.js'; @@ -10,13 +10,15 @@ export async function verifyCredential({config, credential, checks} = {}) { const documentLoader = await createDocumentLoader({config}); const suite = createSuites(); + // only check credential status when option is set + const checkStatus = checks.includes('credentialStatus') ? + _checkStatus : undefined; + const result = await vc.verifyCredential({ credential, documentLoader, suite, - // only check credential status when option is set - checkStatus: checks.includes('credentialStatus') ? - checkStatus : () => ({verified: true}) + checkStatus }); // if proof should have been checked but wasn't due to an error, // try to run the check again using the VC's issuance date @@ -28,9 +30,7 @@ export async function verifyCredential({config, credential, checks} = {}) { documentLoader, suite, now: new Date(credential.issuanceDate), - // only check credential status when option is set - checkStatus: checks.includes('credentialStatus') ? - checkStatus : () => ({verified: true}) + checkStatus }); if(proofResult.verified) { // overlay original (failed) results on top of proof results @@ -57,7 +57,7 @@ export async function verifyPresentation({ documentLoader: await createDocumentLoader({config}), suite: createSuites(), unsignedPresentation: !checks.includes('proof'), - checkStatus + checkStatus: _checkStatus }; return vc.verify(verifyOptions); } diff --git a/lib/status.js b/lib/status.js index 769a48a..b30a381 100644 --- a/lib/status.js +++ b/lib/status.js @@ -1,24 +1,32 @@ /*! - * Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved. + * Copyright (c) 2019-2024 Digital Bazaar, Inc. All rights reserved. */ +import { + checkStatus as bitstringStatusListCheckStatus, + statusTypeMatches as bitstringStatusListStatusTypeMatches +} from '@digitalbazaar/vc-bitstring-status-list'; import { checkStatus as revocationListCheckStatus, statusTypeMatches as revocationListStatusTypeMatches } from '@digitalbazaar/vc-revocation-list'; import { - checkStatus as statusListCheckStatus, - statusTypeMatches as statusListStatusTypeMatches + checkStatus as statusList2020CheckStatus, + statusTypeMatches as statusList2020StatusTypeMatches } from '@digitalbazaar/vc-status-list'; import assert from 'assert-plus'; const handlerMap = new Map(); +handlerMap.set('BitstringStatusListEntry', { + checkStatus: bitstringStatusListCheckStatus, + statusTypeMatches: bitstringStatusListStatusTypeMatches +}); handlerMap.set('RevocationList2020Status', { checkStatus: revocationListCheckStatus, statusTypeMatches: revocationListStatusTypeMatches }); handlerMap.set('StatusList2021Entry', { - checkStatus: statusListCheckStatus, - statusTypeMatches: statusListStatusTypeMatches + checkStatus: statusList2020CheckStatus, + statusTypeMatches: statusList2020StatusTypeMatches }); export async function checkStatus(options = {}) { diff --git a/package.json b/package.json index cafee2c..2932c42 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@digitalbazaar/eddsa-2022-cryptosuite": "^1.0.0", "@digitalbazaar/eddsa-rdfc-2022-cryptosuite": "^1.1.0", "@digitalbazaar/vc": "^7.0.0", + "@digitalbazaar/vc-bitstring-status-list": "^2.0.0", "@digitalbazaar/vc-revocation-list": "^7.0.0", "@digitalbazaar/vc-status-list": "^8.0.0", "assert-plus": "^1.0.0", diff --git a/test/mocha/30-credential-status.js b/test/mocha/30-bsl-credential-status.js similarity index 51% rename from test/mocha/30-credential-status.js rename to test/mocha/30-bsl-credential-status.js index 99ea731..4cc509d 100644 --- a/test/mocha/30-credential-status.js +++ b/test/mocha/30-bsl-credential-status.js @@ -1,13 +1,11 @@ /*! - * Copyright (c) 2019-2023 Digital Bazaar, Inc. All rights reserved. + * Copyright (c) 2019-2024 Digital Bazaar, Inc. All rights reserved. */ import * as helpers from './helpers.js'; -import * as statusListCtx from '@digitalbazaar/vc-status-list-context'; import * as vc from '@digitalbazaar/vc'; import {agent} from '@bedrock/https-agent'; import {documentLoader as brDocLoader} from '@bedrock/jsonld-document-loader'; import {CapabilityAgent} from '@digitalbazaar/webkms-client'; -import {createRequire} from 'node:module'; import {Ed25519Signature2020} from '@digitalbazaar/ed25519-signature-2020'; import { Ed25519VerificationKey2020 @@ -17,12 +15,8 @@ import {fileURLToPath} from 'node:url'; import fs from 'node:fs'; import {httpClient} from '@digitalbazaar/http-client'; import https from 'node:https'; -import {klona} from 'klona'; import path from 'node:path'; -const require = createRequire(import.meta.url); -const revocationListCtx = require('vc-revocation-list-context'); - import {mockData} from './mock.data.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -30,30 +24,24 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const {baseUrl} = mockData; const serviceType = 'vc-verifier'; -const VC_SL_CONTEXT_URL = statusListCtx.constants.CONTEXT_URL_V1; -const VC_RL_CONTEXT_URL = - revocationListCtx.constants.VC_REVOCATION_LIST_CONTEXT_V1_URL; +const VC_V2_CONTEXT_URL = 'https://www.w3.org/ns/credentials/v2'; const encodedList100k = - 'H4sIAAAAAAAAA-3BMQEAAADCoPVPbQsvoAAAAAAAAAAAAAAAAP4GcwM92tQwAAA'; + 'uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQsvoAAAAAAAAAAAAAAAAP4GcwM92tQwAAA'; const encodedList100KWith50KthRevoked = - 'H4sIAAAAAAAAA-3OMQ0AAAgDsElHOh72EJJWQRMAAAAAAIDWXAcAAAAAAIDHFvRitn7UMAAA'; + 'uH4sIAAAAAAAAA-3OMQ0AAAgDsElHOh72EJJWQRMAAAAAAIDWXAcAAAAAAIDHFvRitn7UMAAA'; const key = fs.readFileSync(__dirname + '/key.pem'); const cert = fs.readFileSync(__dirname + '/cert.pem'); -let slCredentialRevocation; -let unsignedCredentialSl2021TypeRevocation; -let slCredentialSuspension; -let unsignedCredentialSl2021TypeSuspension; -let unsignedCredentialSl2021WithUnmatchingStatusPurpose; -let revokedSlCredential; +let slcRevocation; +let slcSuspension; +let unsignedCredentialStatusPurposeRevocation; +let unsignedCredentialStatusPurposeSuspension; +let unsignedCredentialWithUnmatchingStatusPurpose; +let revokedSlc; let revokedUnsignedCredential; -let rlCredential; -let unsignedCredentialRL2020Type; -let revokedRlCredential; -let revokedUnsignedCredential2; -// load docs from test server (e.g., load RL VCs and SL VCs) +// load docs from test server (e.g., load SL VCs) let testServerBaseUrl; async function _documentLoader(url) { if(url.startsWith(testServerBaseUrl)) { @@ -76,30 +64,27 @@ function _startServer({app}) { testServerBaseUrl = BASE_URL; console.log(`Test server listening at ${BASE_URL}`); - // Status List 2021 Credential with statusPurpose `revocation` - slCredentialRevocation = { + // SLC with statusPurpose `revocation` + slcRevocation = { '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_SL_CONTEXT_URL + VC_V2_CONTEXT_URL ], id: `${BASE_URL}/status/748a7d8e-9111-11ec-a934-10bf48838a41`, issuer: 'did:key:z6Mktpn6cXks1PBKLMgZH2VaahvCtBMF6K8eCa7HzrnuYLZv', - issuanceDate: '2022-01-10T04:24:12.164Z', - type: ['VerifiableCredential', 'StatusList2021Credential'], + validFrom: '2022-01-10T04:24:12.164Z', + type: ['VerifiableCredential', 'BitstringStatusListCredential'], credentialSubject: { id: `${BASE_URL}/status/748a7d8e-9111-11ec-a934-10bf48838a41#list`, - type: 'StatusList2021', + type: 'BitstringStatusList', statusPurpose: 'revocation', encodedList: encodedList100k } }; - // Unsigned 2021 Credential with "credentialStatus.statusPurpose" - // `revocation` - unsignedCredentialSl2021TypeRevocation = { + // unsigned VC with "credentialStatus.statusPurpose" `revocation` + unsignedCredentialStatusPurposeRevocation = { '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_SL_CONTEXT_URL, + VC_V2_CONTEXT_URL, 'https://w3id.org/security/suites/ed25519-2020/v1' ], id: 'urn:uuid:a0418a78-7924-11ea-8a23-10bf48838a41', @@ -110,38 +95,35 @@ function _startServer({app}) { }, credentialStatus: { id: `${BASE_URL}/status/748a7d8e-9111-11ec-a934-10bf48838a41#67342`, - type: 'StatusList2021Entry', + type: 'BitstringStatusListEntry', statusPurpose: 'revocation', statusListIndex: '67342', - statusListCredential: slCredentialRevocation.id + statusListCredential: slcRevocation.id }, - issuer: slCredentialRevocation.issuer, + issuer: slcRevocation.issuer, }; - // Status List 2021 Credential with statusPurpose `suspension` - slCredentialSuspension = { + // SLC with statusPurpose `suspension` + slcSuspension = { '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_SL_CONTEXT_URL + VC_V2_CONTEXT_URL ], id: `${BASE_URL}/status/5d3e7a97-1121-11ec-9b38-10bf48838a41`, issuer: 'did:key:z6Mktpn6cXks1PBKLMgZH2VaahvCtBMF6K8eCa7HzrnuYLZv', - issuanceDate: '2022-01-10T04:24:12.164Z', - type: ['VerifiableCredential', 'StatusList2021Credential'], + validFrom: '2022-01-10T04:24:12.164Z', + type: ['VerifiableCredential', 'BitstringStatusListCredential'], credentialSubject: { id: `${BASE_URL}/status/5d3e7a97-1121-11ec-9b38-10bf48838a41#list`, - type: 'StatusList2021', + type: 'BitstringStatusList', statusPurpose: 'suspension', encodedList: encodedList100k } }; - // Unsigned 2021 Credential with "credentialStatus.statusPurpose" - // `suspension` - unsignedCredentialSl2021TypeSuspension = { + // unsigned VC with "credentialStatus.statusPurpose" `suspension` + unsignedCredentialStatusPurposeSuspension = { '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_SL_CONTEXT_URL, + VC_V2_CONTEXT_URL, 'https://w3id.org/security/suites/ed25519-2020/v1' ], id: 'urn:uuid:a0418a78-7924-11ea-8a23-10bf48838a41', @@ -152,19 +134,18 @@ function _startServer({app}) { }, credentialStatus: { id: `${BASE_URL}/status/5d3e7a97-1121-11ec-9b38-10bf48838a41#67342`, - type: 'StatusList2021Entry', + type: 'BitstringStatusListEntry', statusPurpose: 'suspension', statusListIndex: '67342', - statusListCredential: slCredentialSuspension.id + statusListCredential: slcSuspension.id }, - issuer: slCredentialSuspension.issuer, + issuer: slcSuspension.issuer, }; - // Unsigned 2021 Credential with unmatching status purpose - unsignedCredentialSl2021WithUnmatchingStatusPurpose = { + // unsigned VC with unmatching status purpose + unsignedCredentialWithUnmatchingStatusPurpose = { '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_SL_CONTEXT_URL, + VC_V2_CONTEXT_URL, 'https://w3id.org/security/suites/ed25519-2020/v1' ], id: 'urn:uuid:a0418a78-7924-11ea-8a23-10bf48838a41', @@ -175,95 +156,37 @@ function _startServer({app}) { }, credentialStatus: { id: `${BASE_URL}/status/748a7d8e-9111-11ec-a934-10bf48838a41#67342`, - type: 'StatusList2021Entry', + type: 'BitstringStatusListEntry', // intentionally set status purpose that does not match status purpose // of sl credential that it fetches. statusPurpose: 'suspension', statusListIndex: '67342', // intentionally point `statusListCredential` to a sl credential // with status purpose `revocation`. - statusListCredential: slCredentialRevocation.id + statusListCredential: slcRevocation.id }, - issuer: slCredentialRevocation.issuer, + issuer: slcRevocation.issuer, }; - // Revoked Status List 2021 Credential - revokedSlCredential = klona(slCredentialRevocation); + // revoked SLC + revokedSlc = structuredClone(slcRevocation); - revokedSlCredential.id = + revokedSlc.id = `${BASE_URL}/status/8ec30054-9111-11ec-9ab5-10bf48838a41`, - revokedSlCredential.credentialSubject.encodedList = + revokedSlc.credentialSubject.encodedList = encodedList100KWith50KthRevoked; - revokedSlCredential.credentialSubject.id = + revokedSlc.credentialSubject.id = `${BASE_URL}/status/8ec30054-9111-11ec-9ab5-10bf48838a41#list`; - // Revoked Unsigned 2021 Credential - revokedUnsignedCredential = klona(unsignedCredentialSl2021TypeRevocation); + // revoked unsigned SLC + revokedUnsignedCredential = structuredClone( + unsignedCredentialStatusPurposeRevocation); revokedUnsignedCredential.credentialStatus.id = - `${revokedSlCredential.id}#50000`; + `${revokedSlc.id}#50000`; revokedUnsignedCredential.credentialStatus.statusListIndex = 50000; revokedUnsignedCredential.credentialStatus.statusListCredential = - `${revokedSlCredential.id}`; - revokedUnsignedCredential.issuer = revokedSlCredential.issuer; - - // Revocation List 2020 Credential - rlCredential = { - '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_RL_CONTEXT_URL - ], - id: `${BASE_URL}/status/9d5a3fb0-9111-11ec-862d-10bf48838a41`, - issuer: 'did:key:z6Mktpn6cXks1PBKLMgZH2VaahvCtBMF6K8eCa7HzrnuYLZv', - issuanceDate: '2022-01-10T04:24:12.164Z', - type: ['VerifiableCredential', 'RevocationList2020Credential'], - credentialSubject: { - id: `${BASE_URL}/status/9d5a3fb0-9111-11ec-862d-10bf48838a41#list`, - type: 'RevocationList2020', - encodedList: encodedList100k - } - }; - - // Unsigned 2020 Credential - unsignedCredentialRL2020Type = { - '@context': [ - 'https://www.w3.org/2018/credentials/v1', - VC_RL_CONTEXT_URL, - 'https://w3id.org/security/suites/ed25519-2020/v1' - ], - id: 'urn:uuid:a0418a78-7924-11ea-8a23-10bf48838a41', - type: ['VerifiableCredential', 'example:TestCredential'], - credentialSubject: { - id: 'urn:uuid:4886029a-7925-11ea-9274-10bf48838a41', - 'example:test': 'foo' - }, - issuanceDate: '2022-01-11T19:23:24Z', - credentialStatus: { - id: `${BASE_URL}/status/9d5a3fb0-9111-11ec-862d-10bf48838a41#67342`, - type: 'RevocationList2020Status', - revocationListIndex: '67342', - revocationListCredential: rlCredential.id - }, - issuer: rlCredential.issuer, - }; - - // Revoked Revocation List 2020 Credential - revokedRlCredential = klona(rlCredential); - - revokedRlCredential.id = - `${BASE_URL}/status/a63896b8-9111-11ec-9fd2-10bf48838a41`, - revokedRlCredential.credentialSubject.encodedList = - encodedList100KWith50KthRevoked; - revokedRlCredential.credentialSubject.id = - `${BASE_URL}/status/a63896b8-9111-11ec-9fd2-10bf48838a41#list`; - - // Revoked Unsigned 2020 Credential - revokedUnsignedCredential2 = klona(unsignedCredentialRL2020Type); - revokedUnsignedCredential2.credentialStatus.id = - `${revokedRlCredential.id}#50000`; - revokedUnsignedCredential2.credentialStatus.revocationListIndex = 50000; - revokedUnsignedCredential2.credentialStatus.revocationListCredential = - `${revokedRlCredential.id}`; - revokedUnsignedCredential2.issuer = revokedRlCredential.issuer; + `${revokedSlc.id}`; + revokedUnsignedCredential.issuer = revokedSlc.issuer; return resolve(server); }); @@ -277,32 +200,20 @@ app.use(express.json()); app.get('/status/748a7d8e-9111-11ec-a934-10bf48838a41', // eslint-disable-next-line no-unused-vars (req, res, next) => { - // responds with a valid status list 2021 type credential - res.json(slCredentialRevocation); + // responds with a valid SLC + res.json(slcRevocation); }); app.get('/status/5d3e7a97-1121-11ec-9b38-10bf48838a41', // eslint-disable-next-line no-unused-vars (req, res, next) => { - // responds with a valid status list 2021 type credential - res.json(slCredentialSuspension); + // responds with a valid SLC + res.json(slcSuspension); }); app.get('/status/8ec30054-9111-11ec-9ab5-10bf48838a41', // eslint-disable-next-line no-unused-vars (req, res, next) => { - // responds with a revoked status list 2021 type credential - res.json(revokedSlCredential); - }); -app.get('/status/9d5a3fb0-9111-11ec-862d-10bf48838a41', - // eslint-disable-next-line no-unused-vars - (req, res, next) => { - // responds with a valid revocation list 2020 type credential - res.json(rlCredential); - }); -app.get('/status/a63896b8-9111-11ec-9fd2-10bf48838a41', - // eslint-disable-next-line no-unused-vars - (req, res, next) => { - // responds with a revoked revocation list 2020 type credential - res.json(revokedRlCredential); + // responds with a revoked SLC + res.json(revokedSlc); }); let server; before(async () => { @@ -312,7 +223,7 @@ after(async () => { server.close(); }); -describe('verify credential status', () => { +describe('verify BitstringStatusList credential status', () => { let keyData; let keyPair; let suite; @@ -383,15 +294,14 @@ describe('verify credential status', () => { verifierId = verifierConfig.id; rootZcap = `urn:zcap:root:${encodeURIComponent(verifierId)}`; }); - it('should verify "StatusList2021Credential" type with "statusPurpose" ' + - 'revocation', async () => { - slCredentialRevocation = await vc.issue({ - credential: slCredentialRevocation, + it('should verify VC w/ "statusPurpose" revocation', async () => { + slcRevocation = await vc.issue({ + credential: slcRevocation, documentLoader: _documentLoader, suite }); const verifiableCredential = await vc.issue({ - credential: unsignedCredentialSl2021TypeRevocation, + credential: unsignedCredentialStatusPurposeRevocation, documentLoader: _documentLoader, suite }); @@ -416,7 +326,7 @@ describe('verify credential status', () => { should.exist(result.data.verified); result.data.verified.should.be.a('boolean'); result.data.verified.should.equal(true); - const {checks} = result.data; + const {checks, statusResult} = result.data; checks.should.be.an('array'); checks.should.have.length(2); checks.should.be.an('array'); @@ -424,19 +334,31 @@ describe('verify credential status', () => { should.exist(result.data.results); result.data.results.should.be.an('array'); result.data.results.should.have.length(1); - const [r] = result.data.results; - r.verified.should.be.a('boolean'); - r.verified.should.equal(true); + { + const [r] = result.data.results; + r.verified.should.be.a('boolean'); + r.verified.should.equal(true); + } + { + should.exist(statusResult); + statusResult.should.be.an('object'); + should.exist(statusResult.results); + statusResult.results.should.be.an('array'); + statusResult.results.should.have.length(1); + const [r] = statusResult.results; + r.verified.should.be.a('boolean'); + r.verified.should.equal(true); + r.status.should.equal(false); + } }); - it('should verify "StatusList2021Credential" type with "statusPurpose" ' + - 'suspension', async () => { - slCredentialSuspension = await vc.issue({ - credential: slCredentialSuspension, + it('should verify VC w/ "statusPurpose" suspension', async () => { + slcSuspension = await vc.issue({ + credential: slcSuspension, documentLoader: _documentLoader, suite }); const verifiableCredential = await vc.issue({ - credential: unsignedCredentialSl2021TypeSuspension, + credential: unsignedCredentialStatusPurposeSuspension, documentLoader: _documentLoader, suite }); @@ -461,7 +383,7 @@ describe('verify credential status', () => { should.exist(result.data.verified); result.data.verified.should.be.a('boolean'); result.data.verified.should.equal(true); - const {checks} = result.data; + const {checks, statusResult} = result.data; checks.should.be.an('array'); checks.should.have.length(2); checks.should.be.an('array'); @@ -469,19 +391,31 @@ describe('verify credential status', () => { should.exist(result.data.results); result.data.results.should.be.an('array'); result.data.results.should.have.length(1); - const [r] = result.data.results; - r.verified.should.be.a('boolean'); - r.verified.should.equal(true); + { + const [r] = result.data.results; + r.verified.should.be.a('boolean'); + r.verified.should.equal(true); + } + { + should.exist(statusResult); + statusResult.should.be.an('object'); + should.exist(statusResult.results); + statusResult.results.should.be.an('array'); + statusResult.results.should.have.length(1); + const [r] = statusResult.results; + r.verified.should.be.a('boolean'); + r.verified.should.equal(true); + r.status.should.equal(false); + } }); - it('should throw error if "statusPurpose" of the slCredential does not ' + - 'match the "statusPurpose" of the credentialStatus', async () => { - slCredentialRevocation = await vc.issue({ - credential: slCredentialRevocation, + it('should fail if "statusPurpose" of the SLC does not match', async () => { + slcRevocation = await vc.issue({ + credential: slcRevocation, documentLoader: _documentLoader, suite }); const verifiableCredential = await vc.issue({ - credential: unsignedCredentialSl2021WithUnmatchingStatusPurpose, + credential: unsignedCredentialWithUnmatchingStatusPurpose, documentLoader: _documentLoader, suite }); @@ -510,62 +444,14 @@ describe('verify credential status', () => { 'The status purpose "revocation" of the status list credential ' + 'does not match the status purpose "suspension" in the credential.'); }); - it('should fail to verify a revoked "StatusList2021Credential" type', - async () => { - revokedSlCredential = await vc.issue({ - credential: revokedSlCredential, - documentLoader: _documentLoader, - suite - }); - const verifiableCredential = await vc.issue({ - credential: revokedUnsignedCredential, - documentLoader: _documentLoader, - suite - }); - let error; - let result; - try { - const zcapClient = helpers.createZcapClient({capabilityAgent}); - result = await zcapClient.write({ - url: `${verifierId}/credentials/verify`, - capability: rootZcap, - json: { - options: { - checks: ['credentialStatus'], - }, - verifiableCredential - } - }); - } catch(e) { - error = e; - } - should.exist(error); - should.not.exist(result); - error.data.verified.should.be.a('boolean'); - error.data.verified.should.equal(false); - const {checks, error: {message: errorMsg}} = error.data; - checks.should.be.an('array'); - checks.should.have.length(1); - errorMsg.should.equal('The credential failed a status check.'); - error.data.statusResult.verified.should.equal(false); - const [{check}] = checks; - check.should.be.an('array'); - check.should.eql(['credentialStatus']); - should.exist(error.data.results); - error.data.results.should.be.an('array'); - error.data.results.should.have.length(1); - const [r] = error.data.results; - r.verified.should.be.a('boolean'); - r.verified.should.equal(true); - }); - it('should verify "RevocationList2020Credential" type', async () => { - rlCredential = await vc.issue({ - credential: rlCredential, + it('should fail to verify revoked VC', async () => { + revokedSlc = await vc.issue({ + credential: revokedSlc, documentLoader: _documentLoader, suite }); const verifiableCredential = await vc.issue({ - credential: unsignedCredentialRL2020Type, + credential: revokedUnsignedCredential, documentLoader: _documentLoader, suite }); @@ -578,7 +464,7 @@ describe('verify credential status', () => { capability: rootZcap, json: { options: { - checks: ['proof', 'credentialStatus'], + checks: ['credentialStatus'], }, verifiableCredential } @@ -586,68 +472,23 @@ describe('verify credential status', () => { } catch(e) { error = e; } - should.not.exist(error); + assertNoError(error); should.exist(result.data.verified); result.data.verified.should.be.a('boolean'); result.data.verified.should.equal(true); - const {checks} = result.data; + const {checks, statusResult} = result.data; checks.should.be.an('array'); - checks.should.have.length(2); + checks.should.have.length(1); checks.should.be.an('array'); - checks.should.eql(['proof', 'credentialStatus']); - should.exist(result.data.results); - result.data.results.should.be.an('array'); - result.data.results.should.have.length(1); - const [r] = result.data.results; + checks.should.eql(['credentialStatus']); + should.exist(statusResult); + statusResult.should.be.an('object'); + should.exist(statusResult.results); + statusResult.results.should.be.an('array'); + statusResult.results.should.have.length(1); + const [r] = statusResult.results; r.verified.should.be.a('boolean'); r.verified.should.equal(true); + r.status.should.equal(true); }); - it('should fail to verify a revoked "RevocationList2020Credential" type', - async () => { - revokedRlCredential = await vc.issue({ - credential: revokedRlCredential, - documentLoader: _documentLoader, - suite - }); - const verifiableCredential = await vc.issue({ - credential: revokedUnsignedCredential2, - documentLoader: _documentLoader, - suite - }); - let error; - let result; - try { - const zcapClient = helpers.createZcapClient({capabilityAgent}); - result = await zcapClient.write({ - url: `${verifierId}/credentials/verify`, - capability: rootZcap, - json: { - options: { - checks: ['credentialStatus'], - }, - verifiableCredential - } - }); - } catch(e) { - error = e; - } - should.exist(error); - should.not.exist(result); - error.data.verified.should.be.a('boolean'); - error.data.verified.should.equal(false); - const {checks, error: {message: errorMsg}} = error.data; - checks.should.be.an('array'); - checks.should.have.length(1); - errorMsg.should.equal('The credential failed a status check.'); - error.data.statusResult.verified.should.equal(false); - const [{check}] = checks; - check.should.be.an('array'); - check.should.eql(['credentialStatus']); - should.exist(error.data.results); - error.data.results.should.be.an('array'); - error.data.results.should.have.length(1); - const [r] = error.data.results; - r.verified.should.be.a('boolean'); - r.verified.should.equal(true); - }); });