UNPKG

@animo-id/pex

Version:

A Typescript implementation of the v1 and v2 DIF Presentation Exchange specification

186 lines 20.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UriEvaluationHandler = void 0; const jsonpath_1 = require("@astronautlabs/jsonpath"); const ssi_types_1 = require("@sphereon/ssi-types"); const nanoid_1 = require("nanoid"); const ConstraintUtils_1 = require("../../ConstraintUtils"); const types_1 = require("../../types"); const Messages_1 = __importDefault(require("../../types/Messages")); const PexCredentialMapper_1 = require("../../types/PexCredentialMapper"); const abstractEvaluationHandler_1 = require("./abstractEvaluationHandler"); class UriEvaluationHandler extends abstractEvaluationHandler_1.AbstractEvaluationHandler { constructor(client) { super(client); } getName() { return 'UriEvaluation'; } handle(definition, wrappedVcs) { var _a, _b, _c; // This filter is removed in V2 definition.input_descriptors.forEach((inDesc, descriptorIdx) => { const uris = definition.getVersion() !== types_1.PEVersion.v2 ? inDesc.schema.map((so) => so.uri) : []; wrappedVcs.forEach((wvc, wrappedVCIdx) => { const vcUris = UriEvaluationHandler.buildVcContextAndSchemaUris(wvc.credential, definition.getVersion()); this.evaluateUris(wvc, vcUris, uris, descriptorIdx, wrappedVCIdx, definition.getVersion()); }); }); const definitionAllowsDataIntegrity = ((_a = definition.format) === null || _a === void 0 ? void 0 : _a.di) || ((_b = definition.format) === null || _b === void 0 ? void 0 : _b.di_vc) || ((_c = definition.format) === null || _c === void 0 ? void 0 : _c.di_vp); const descriptorMap = this.getResults() .filter((result) => result.status === ConstraintUtils_1.Status.INFO) .map((result) => { var _a, _b, _c, _d; let format = (_a = result.payload) === null || _a === void 0 ? void 0 : _a.format; // This checks if the new data integrity format should be used. // That may be the case if the input descriptor points to credentials that are in ldp_vc or ldp format, // and the presentation definition allows data integrity. if (definitionAllowsDataIntegrity && (format === 'ldp_vc' || format === 'ldp')) { const wvcs = jsonpath_1.JSONPath.nodes(wrappedVcs, result.verifiable_credential_path).map((node) => node.value); // check if all vc's have a data integrity proof const vcDataIntegrityProofs = wvcs.map((vc) => { if (vc.type !== ssi_types_1.OriginalType.JSONLD || !vc.credential.proof) return []; const proofs = Array.isArray(vc.credential.proof) ? vc.credential.proof : [vc.credential.proof]; const dataIntegrityProofs = proofs.filter((proof) => proof.type === 'DataIntegrityProof' && proof.cryptosuite !== undefined); return dataIntegrityProofs; }); // determine the common cryptosuites of all vc's const commonCryptosuites = vcDataIntegrityProofs.reduce((a, b) => a.filter((c) => b.includes(c))); // the input descriptor should also allow data integrity const inputDescriptor = jsonpath_1.JSONPath.nodes(definition, result.input_descriptor_path)[0].value; const inputDescriptorAllowsDataIntegrity = !inputDescriptor['format'] || ((_b = inputDescriptor === null || inputDescriptor === void 0 ? void 0 : inputDescriptor.format) === null || _b === void 0 ? void 0 : _b.di) || ((_c = inputDescriptor === null || inputDescriptor === void 0 ? void 0 : inputDescriptor.format) === null || _c === void 0 ? void 0 : _c.di_vc) || ((_d = inputDescriptor === null || inputDescriptor === void 0 ? void 0 : inputDescriptor.format) === null || _d === void 0 ? void 0 : _d.di_vp); if (commonCryptosuites.length > 0 && inputDescriptorAllowsDataIntegrity) { format = 'di_vc'; } } const inputDescriptor = jsonpath_1.JSONPath.nodes(definition, result.input_descriptor_path)[0].value; return { id: inputDescriptor.id, format, path: result.verifiable_credential_path, }; }); // The presentation submission is being created in this handler, then updated in subsequent handler. // TODO: This approach needs to be refactored for a new Major version. // Also there is no apparent need for the indirection and state in this class. // Simply do the first loops and amend the presentation submission in every loop. if (this.client.generatePresentationSubmission && (!this.presentationSubmission || Object.keys(this.presentationSubmission).length === 0)) { this.presentationSubmission = { id: (0, nanoid_1.nanoid)(), definition_id: definition.id, descriptor_map: descriptorMap, }; } } evaluateUris(wvc, verifiableCredentialUris, inputDescriptorsUris, idIdx, vcIdx, pdVersion) { let hasAnyMatch = false; if (pdVersion === types_1.PEVersion.v1) { for (let i = 0; i < inputDescriptorsUris.length; i++) { if (UriEvaluationHandler.containsHashlink(inputDescriptorsUris[i])) { this.getResults().push(this.createWarnResultObject(idIdx, vcIdx)); } } for (let i = 0; i < verifiableCredentialUris.length; i++) { if (inputDescriptorsUris.find((el) => el === verifiableCredentialUris[i]) != undefined) { hasAnyMatch = true; } } } else { hasAnyMatch = true; } if (hasAnyMatch) { this.getResults().push(this.createSuccessResultObject(wvc, inputDescriptorsUris, idIdx, vcIdx)); } else { this.getResults().push(this.createErrorResultObject(wvc, inputDescriptorsUris, idIdx, vcIdx)); } } static buildVcContextAndSchemaUris(credential, version) { const uris = []; // W3C credential if (PexCredentialMapper_1.PexCredentialMapper.isW3cCredential(credential)) { if (Array.isArray(credential['@context'])) { credential['@context'].forEach((value) => uris.push(value)); } else { uris.push(credential['@context']); } if (Array.isArray(credential.credentialSchema) && credential.credentialSchema.length > 0) { credential.credentialSchema.forEach((element) => uris.push(element.id)); } else if (credential.credentialSchema) { uris.push(credential.credentialSchema.id); } if (version === types_1.PEVersion.v1) { // JWT VC Profile and MS Entry Verified ID do use the schema from V1 to match against types in the VC Array.isArray(credential.type) ? credential.type.forEach((type) => uris.push(type)) : credential.type ? uris.push(credential.type) : undefined; } } // NOTE: we add the `vct` field of an SD-JWT to the list of uris, to allow SD-JWT // to work with PEX v1 in the same way that JWT vcs can work with pex v1. If we don't // add this, then SD-JWTs can only be used with PEX v2. if (PexCredentialMapper_1.PexCredentialMapper.isSdJwtDecodedCredential(credential)) { if (version === types_1.PEVersion.v1) { uris.push(credential.decodedPayload.vct); } } return uris; } createSuccessResultObject(wvc, inputDescriptorsUris, idIdx, vcIdx) { const result = this.createResult(idIdx, vcIdx); result.status = ConstraintUtils_1.Status.INFO; result.message = Messages_1.default.URI_EVALUATION_PASSED; result.payload = { format: wvc.format, vcContext: PexCredentialMapper_1.PexCredentialMapper.isW3cCredential(wvc.credential) ? wvc.credential['@context'] : undefined, vcCredentialSchema: PexCredentialMapper_1.PexCredentialMapper.isW3cCredential(wvc.credential) ? wvc.credential.credentialSchema : undefined, inputDescriptorsUris, }; return result; } createErrorResultObject(wvc, inputDescriptorsUris, idIdx, vcIdx) { const result = this.createResult(idIdx, vcIdx); result.status = ConstraintUtils_1.Status.ERROR; result.message = Messages_1.default.URI_EVALUATION_DIDNT_PASS; result.payload = { format: wvc.format, vcContext: PexCredentialMapper_1.PexCredentialMapper.isW3cCredential(wvc.credential) ? wvc.credential['@context'] : undefined, vcCredentialSchema: PexCredentialMapper_1.PexCredentialMapper.isW3cCredential(wvc.credential) ? wvc.credential.credentialSchema : undefined, inputDescriptorsUris, }; return result; } createWarnResultObject(idIdx, vcIdx) { const result = this.createResult(idIdx, vcIdx); result.status = ConstraintUtils_1.Status.WARN; result.message = Messages_1.default.URI_EVALUATION_DIDNT_PASS; result.payload = Messages_1.default.INPUT_DESCRIPTOR_CONTEXT_CONTAINS_HASHLINK_VERIFICATION_NOT_SUPPORTED; return result; } createResult(idIdx, vcIdx) { return { input_descriptor_path: `$.input_descriptors[${idIdx}]`, verifiable_credential_path: `$[${vcIdx}]`, evaluator: this.getName(), status: ConstraintUtils_1.Status.INFO, message: undefined, }; } static containsHashlink(url) { return !(url.matchAll(UriEvaluationHandler.HASHLINK_QUERY_URL_REGEX).next().done && url.matchAll(UriEvaluationHandler.HASHLINK_URL_ENCODED_REGEX).next().done); } } exports.UriEvaluationHandler = UriEvaluationHandler; UriEvaluationHandler.HASHLINK_URL_ENCODED_REGEX = /hl:[a-zA-Z0-9]+:[a-zA-Z0-9]+/g; UriEvaluationHandler.HASHLINK_QUERY_URL_REGEX = /https*?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)(hl=[a-zA-Z0-9]+)/g; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXJpRXZhbHVhdGlvbkhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWIvZXZhbHVhdGlvbi9oYW5kbGVycy91cmlFdmFsdWF0aW9uSGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxzREFBeUQ7QUFFekQsbURBQXFIO0FBQ3JILG1DQUFnQztBQUVoQywyREFBK0M7QUFDL0MsdUNBQTJHO0FBQzNHLG9FQUErQztBQUMvQyx5RUFBbUc7QUFJbkcsMkVBQXdFO0FBRXhFLE1BQWEsb0JBQXFCLFNBQVEscURBQXlCO0lBQ2pFLFlBQVksTUFBd0I7UUFDbEMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hCLENBQUM7SUFFTSxPQUFPO1FBQ1osT0FBTyxlQUFlLENBQUM7SUFDekIsQ0FBQztJQU1NLE1BQU0sQ0FBQyxVQUEyQyxFQUFFLFVBQXlDOztRQUNsRywrQkFBK0I7UUFDSSxVQUFXLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBeUIsRUFBRSxhQUFxQixFQUFFLEVBQUU7WUFDNUgsTUFBTSxJQUFJLEdBQWEsVUFBVSxDQUFDLFVBQVUsRUFBRSxLQUFLLGlCQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQWdDLEVBQUUsWUFBb0IsRUFBRSxFQUFFO2dCQUM1RSxNQUFNLE1BQU0sR0FBYSxvQkFBb0IsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO2dCQUNuSCxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxF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