@@ -101,6 +101,7 @@ module.exports = {
101
101
* @property {object } statusResult
102
102
* @property {Array } results
103
103
* @property {object } error
104
+ * @property {object[] } log - Optional event log.
104
105
*/
105
106
106
107
/**
@@ -251,11 +252,11 @@ async function verifyCredential(options = {}) {
251
252
throw new TypeError (
252
253
'A "credential" property is required for verifying.' ) ;
253
254
}
254
- return _verifyCredential ( options ) ;
255
+ return await _verifyCredential ( options ) ;
255
256
} catch ( error ) {
256
257
return {
257
258
verified : false ,
258
- results : [ { credential, verified : false , error} ] ,
259
+ results : [ { credential, verified : false , error, log : error . log } ] ,
259
260
error
260
261
} ;
261
262
}
@@ -285,8 +286,13 @@ async function verifyCredential(options = {}) {
285
286
async function _verifyCredential ( options = { } ) {
286
287
const { credential, checkStatus, now} = options ;
287
288
288
- // run common credential checks
289
- _checkCredential ( { credential, now} ) ;
289
+ // Fine grained result log containing checks performed. Example:
290
+ // [{id: 'valid_signature', valid: true},
291
+ // {id: 'expiration', valid: true}]
292
+ const log = [ ] ;
293
+
294
+ // run common credential checks (add check results to log)
295
+ _checkCredential ( { credential, log, now} ) ;
290
296
291
297
// if credential status is provided, a `checkStatus` function must be given
292
298
if ( credential . credentialStatus && typeof options . checkStatus !== 'function' ) {
@@ -302,21 +308,40 @@ async function _verifyCredential(options = {}) {
302
308
controller
303
309
} ) ;
304
310
305
- const result = await jsigs . verify (
306
- credential , { purpose, documentLoader, ...options } ) ;
311
+ let result ;
312
+ try {
313
+ result = await jsigs . verify (
314
+ credential , { purpose, documentLoader, ...options } ) ;
315
+ } catch ( error ) {
316
+ log . push ( { id : 'valid_signature' , valid : false } ) ;
317
+ error . log = log ;
318
+ throw error ;
319
+ }
307
320
308
321
// if verification has already failed, skip status check
309
322
if ( ! result . verified ) {
310
323
return result ;
311
324
}
312
325
313
- if ( credential . credentialStatus ) {
326
+ log . push ( { id : 'valid_signature' , valid : true } ) ;
327
+ log . push ( { id : 'issuer_did_resolves' , valid : true } ) ;
328
+
329
+ if ( checkStatus || credential . credentialStatus ) {
314
330
result . statusResult = await checkStatus ( options ) ;
331
+
315
332
if ( ! result . statusResult . verified ) {
316
333
result . verified = false ;
334
+ log . push ( { id : 'revocation_status' , valid : false } ) ;
335
+ } else {
336
+ log . push ( { id : 'revocation_status' , valid : true } ) ;
317
337
}
338
+ } else {
339
+ log . push ( { id : 'revocation_status' , valid : true } ) ;
340
+ }
341
+ result . log = log ;
342
+ if ( result . results ) {
343
+ result . results [ 0 ] . log = log ;
318
344
}
319
-
320
345
return result ;
321
346
}
322
347
@@ -537,12 +562,14 @@ function _checkPresentation(presentation) {
537
562
* @param {object } options - Options hashmap.
538
563
* @param {object } options.credential - An object that could be a
539
564
* VerifiableCredential.
565
+ * @param {object[] } [options.log] - Optional events log, for fine-grained
566
+ * verification result reporting.
540
567
* @param {string|Date } [options.now] - A string representing date time in
541
568
* ISO 8601 format or an instance of Date. Defaults to current date time.
542
569
* @throws {Error }
543
570
* @private
544
571
*/
545
- function _checkCredential ( { credential, now = new Date ( ) } ) {
572
+ function _checkCredential ( { credential, log = [ ] , now = new Date ( ) } ) {
546
573
if ( typeof now === 'string' ) {
547
574
now = new Date ( now ) ;
548
575
}
@@ -636,14 +663,21 @@ function _checkCredential({credential, now = new Date()}) {
636
663
const { expirationDate} = credential ;
637
664
// check if `expirationDate` property is a date
638
665
if ( ! dateRegex . test ( expirationDate ) ) {
639
- throw new Error (
666
+ log . push ( { id : 'expiration' , valid : false } ) ;
667
+ const error = new Error (
640
668
`"expirationDate" must be a valid date: ${ expirationDate } ` ) ;
669
+ error . log = log ;
670
+ throw error ;
641
671
}
642
672
// check if `now` is after `expirationDate`
643
673
if ( now > new Date ( expirationDate ) ) {
644
- throw new Error ( 'Credential has expired.' ) ;
674
+ log . push ( { id : 'expiration' , valid : false } ) ;
675
+ const error = new Error ( 'Credential has expired.' ) ;
676
+ error . log = log ;
677
+ throw error ;
645
678
}
646
679
}
680
+ log . push ( { id : 'expiration' , valid : true } ) ;
647
681
}
648
682
649
683
function _validateUriId ( { id, propertyName} ) {
0 commit comments