import { IValidationOptions } from '../options/IValidationOptions' ; import { IVerifiableCredentialValidation , VerifiableCredentialValidationResponse } from './VerifiableCredentialValidationResponse' ; import { DidValidation } from './DidValidation' ; import { IExpectedVerifiableCredential , ClaimToken , VerifiableCredentialValidation , ValidationError } from '../index' ; import VerifiableCredentialConstants from '../verifiable_credential/VerifiableCredentialConstants' ; import ErrorHelpers from '../error_handling/ErrorHelpers' ; const errorCode = ( error ) => ErrorHelpers . errorCode ( 'VCSDKVCLD' , error ) ; /**
 * Class for verifiable credential validation
 */ export class VerifiableCredentialValidationJsonLd implements IVerifiableCredentialValidation { param options param expected constructor ( private options , private expected ) { } param verifiableCredential param siopDid returns public async validate ( verifiableCredential , siopDid ) { let validationResponse = { result : true , status : 200 } ; const didValidation = new DidValidation ( this . options , this . expected ) ; validationResponse = await didValidation . validate ( verifiableCredential ) ; if ( ! validationResponse . result ) { return validationResponse ; } const isJwt = typeof verifiableCredential === 'string' ; if ( isJwt ) { validationResponse . payloadObject = validationResponse . payloadObject . vc ; } const context = validationResponse . payloadObject [ VerifiableCredentialConstants . CLAIM_CONTEXT ] ; if ( ! context || context . length === 0 ) { return { result : false , code : errorCode ( 4 ) , detailedError : `The verifiable credential vc property does not contain ${ VerifiableCredentialConstants . CLAIM_CONTEXT }` , status : 403 } ; } if ( context [ 0 ] !== VerifiableCredentialConstants . DEFAULT_VERIFIABLECREDENTIAL_CONTEXT ) { return { result : false , code : errorCode ( 5 ) , detailedError : `The verifiable credential context first element should be ${ VerifiableCredentialConstants . DEFAULT_VERIFIABLECREDENTIAL_CONTEXT }` , status : 403 } ; } let credentialType ; try { credentialType = VerifiableCredentialValidation . getVerifiableCredentialType ( validationResponse . payloadObject ) ; } catch ( exception ) { console . error ( exception . message ) ; return { result : false , code : errorCode ( 5 ) , detailedError : exception . message , innerError : exception , status : 403 } ; } if ( ! validationResponse . payloadObject . credentialSubject ) { return { result : false , code : errorCode ( 6 ) , detailedError : `The verifiable credential with type '${ credentialType }' does not has a credentialSubject property` , status : 403 } ; } if ( isJwt ) { validationResponse = await this . options . checkScopeValidityOnVcTokenDelegate ( validationResponse , this . expected , siopDid ) ; if ( ! validationResponse . result ) { return validationResponse ; } } else { let subjects = [ ] ; if ( ! Array . isArray ( validationResponse . payloadObject . credentialSubject ) ) { subjects . push ( validationResponse . payloadObject . credentialSubject . id ) ; } else { subjects = validationResponse . payloadObject . credentialSubject . map ( ( subject ) => subject . id ) ; } if ( ! subjects . includes ( siopDid ) ) { return { result : false , code : errorCode ( 7 ) , detailedError : `The verifiable credential with type '${ credentialType }', the id in the credentialSubject property does not match the presenter DID: ${ siopDid }` , status : 403 } ; } } if ( this . expected . contractIssuers ) { const contractIssuers = VerifiableCredentialValidation . getIssuersFromExpected ( this . expected , credentialType ) ; if ( ! ( contractIssuers instanceof Array ) ) { return < VerifiableCredentialValidationResponse > contractIssuers ; } if ( ! contractIssuers ) { return { result : false , code : errorCode ( 8 ) , detailedError : `The verifiable credential with type '${ credentialType }' is not expected in '${ JSON . stringify ( this . expected . contractIssuers ) }'` , status : 403 } ; } if ( ! contractIssuers . includes ( validationResponse . issuer ! ) ) { return { result : false , code : errorCode ( 9 ) , detailedError : `The verifiable credential with type '${ credentialType }' is not from a trusted issuer '${ JSON . stringify ( this . expected . contractIssuers ) }'` , status : 403 } ; } } validationResponse . validationResult = { verifiableCredentials : < any > ClaimToken . create ( verifiableCredential , credentialType ) } ; return validationResponse ; } param vc public static getVerifiableCredentialType ( vc ) { const types = vc . type ; if ( ! types || types . length === 0 ) { throw new ValidationError ( `The vc property does not contain type` , errorCode ( 1 ) ) ; } if ( types . length < 2 ) { throw new ValidationError ( `The verifiable credential type property should have two elements` , errorCode ( 2 ) ) ; } if ( types [ 0 ] !== VerifiableCredentialConstants . DEFAULT_VERIFIABLECREDENTIAL_TYPE ) { throw new ValidationError ( `The verifiable credential type first element should be ${ VerifiableCredentialConstants . DEFAULT_VERIFIABLECREDENTIAL_TYPE }` , errorCode ( 3 ) ) ; } return types [ 1 ] ; } param expected param credentialType public static getIssuersFromExpected ( expected , credentialType ? ) { if ( ! expected . contractIssuers ) { return { result : false , status : 500 , code : errorCode ( 10 ) , detailedError : `Expected should have contractIssuers set for verifyableCredential` } ; } let issuers ; if ( expected . contractIssuers instanceof Array ) { if ( expected . contractIssuers . length === 0 ) { return { result : false , status : 500 , code : errorCode ( 11 ) , detailedError : `Expected should have contractIssuers set for verifiableCredential. Empty array presented.` } ; } issuers = < string [ ] > expected . contractIssuers ; } else { if ( ! credentialType ) { return { result : false , status : 500 , code : errorCode ( 12 ) , detailedError : `The credentialType needs to be specified to validate the verifiableCredential.` } ; } if ( ! ( < { [ contract ] : string [ ] ; } > expected . contractIssuers ) [ credentialType ] ) { return { result : false , status : 403 , code : errorCode ( 13 ) , detailedError : `Expected should have contractIssuers set for verifiableCredential. Missing contractIssuers for '${ credentialType }'.` } ; } issuers = < string [ ] > expected . contractIssuers [ credentialType ] ; } return issuers ; } }