@@ -101,6 +101,7 @@ module.exports = {
101101 * @property {object } statusResult
102102 * @property {Array } results
103103 * @property {object } error
104+ * @property {object[] } log - Optional event log.
104105 */
105106
106107/**
@@ -251,11 +252,11 @@ async function verifyCredential(options = {}) {
251252 throw new TypeError (
252253 'A "credential" property is required for verifying.' ) ;
253254 }
254- return _verifyCredential ( options ) ;
255+ return await _verifyCredential ( options ) ;
255256 } catch ( error ) {
256257 return {
257258 verified : false ,
258- results : [ { credential, verified : false , error} ] ,
259+ results : [ { credential, verified : false , error, log : error . log } ] ,
259260 error
260261 } ;
261262 }
@@ -285,8 +286,13 @@ async function verifyCredential(options = {}) {
285286async function _verifyCredential ( options = { } ) {
286287 const { credential, checkStatus, now} = options ;
287288
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} ) ;
290296
291297 // if credential status is provided, a `checkStatus` function must be given
292298 if ( credential . credentialStatus && typeof options . checkStatus !== 'function' ) {
@@ -302,21 +308,40 @@ async function _verifyCredential(options = {}) {
302308 controller
303309 } ) ;
304310
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+ }
307320
308321 // if verification has already failed, skip status check
309322 if ( ! result . verified ) {
310323 return result ;
311324 }
312325
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 ) {
314330 result . statusResult = await checkStatus ( options ) ;
331+
315332 if ( ! result . statusResult . verified ) {
316333 result . verified = false ;
334+ log . push ( { id : 'revocation_status' , valid : false } ) ;
335+ } else {
336+ log . push ( { id : 'revocation_status' , valid : true } ) ;
317337 }
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 ;
318344 }
319-
320345 return result ;
321346}
322347
@@ -537,12 +562,14 @@ function _checkPresentation(presentation) {
537562 * @param {object } options - Options hashmap.
538563 * @param {object } options.credential - An object that could be a
539564 * VerifiableCredential.
565+ * @param {object[] } [options.log] - Optional events log, for fine-grained
566+ * verification result reporting.
540567 * @param {string|Date } [options.now] - A string representing date time in
541568 * ISO 8601 format or an instance of Date. Defaults to current date time.
542569 * @throws {Error }
543570 * @private
544571 */
545- function _checkCredential ( { credential, now = new Date ( ) } ) {
572+ function _checkCredential ( { credential, log = [ ] , now = new Date ( ) } ) {
546573 if ( typeof now === 'string' ) {
547574 now = new Date ( now ) ;
548575 }
@@ -636,14 +663,21 @@ function _checkCredential({credential, now = new Date()}) {
636663 const { expirationDate} = credential ;
637664 // check if `expirationDate` property is a date
638665 if ( ! dateRegex . test ( expirationDate ) ) {
639- throw new Error (
666+ log . push ( { id : 'expiration' , valid : false } ) ;
667+ const error = new Error (
640668 `"expirationDate" must be a valid date: ${ expirationDate } ` ) ;
669+ error . log = log ;
670+ throw error ;
641671 }
642672 // check if `now` is after `expirationDate`
643673 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 ;
645678 }
646679 }
680+ log . push ( { id : 'expiration' , valid : true } ) ;
647681}
648682
649683function _validateUriId ( { id, propertyName} ) {
0 commit comments