@animo-id/pex
Version:
A Typescript implementation of the v1 and v2 DIF Presentation Exchange specification
186 lines • 20.9 kB
JavaScript
;
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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