diff --git a/config.json.example b/config.json.example index 78a93f9..a54816a 100644 --- a/config.json.example +++ b/config.json.example @@ -24,6 +24,23 @@ // The arguments that should be passed to the VC generator. "generatorOptions":"", + // This section overrides the above binary settings in favor of a + // REST API for credential issuance and presentation + "restapi": { + // URL of REST API + "baseUrl": "https://example.com", + // Issuance endpoint + "generator": "/credentials/issue", + // Presentation endpoint + "presentationGenerator": "/presentations/prove", + // Options to be based in request body + "generatorOptions": {}, + // Authorization token type + "oauthTokenType": "Bearer", + // Authorization token + "oauthToken": "" + }, + // Add section features you are explicitly not supporting // For example, to exclude all features, you would: // "sectionsNotSupported": ["basic", ""schema", "refresh", "evidence", "status", "tou", "ldp", "jwt", "zkp"] diff --git a/package.json b/package.json index b885f25..77c1245 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@decentralized-identity/did-auth-jose": "^0.1.13" }, "devDependencies": { + "axios": "^1.5.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "mocha": "^6.1.4" diff --git a/test/vc-data-model-1.0/util.js b/test/vc-data-model-1.0/util.js index 1fff430..9cc9fd9 100644 --- a/test/vc-data-model-1.0/util.js +++ b/test/vc-data-model-1.0/util.js @@ -4,10 +4,39 @@ 'use strict'; const path = require('path'); const util = require('util'); +const fs = require('fs'); +const axios = require('axios'); const exec = util.promisify(require('child_process').exec); async function generate(file, options) { + if (options.restapi) { + return await generateFromRestapi(file, options.restapi); + } else { + return await generateFromBinary(file, options); + } +} + +async function generateFromRestapi(file, options) { + const url = `${options.baseUrl}${options.generator}`; + const fileContent = fs.readFileSync(path.join(__dirname, 'input', file), 'utf8'); + const dataToIssue = createIssuanceData(fileContent, options.generatorOptions); + const axiosOptions = { + timeout: 2000, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `${options.oauthTokenType} ${options.oauthToken}` + } + } + try { + const response = await axios.post(url, dataToIssue, axiosOptions); + return response.data?.verifiableCredential ? response.data.verifiableCredential : {}; + } catch (error) { + throw new Error('Failed to get valid response'); + } +} + +async function generateFromBinary(file, options) { options = options || {}; const {stdout, stderr} = await exec(options.generator + ' ' + options.generatorOptions + ' ' + path.join(__dirname, 'input', file)); @@ -32,8 +61,34 @@ async function generateJwt(file, options) { return stdout; } - async function generatePresentation(file, options) { + if (options.restapi) { + return await generatePresentationFromRestapi(file, options.restapi); + } else { + return await generatePresentationFromBinary(file, options); + } +} + +async function generatePresentationFromRestapi(file, options) { + const fileContent = fs.readFileSync(path.join(__dirname, 'input', file), 'utf8'); + const dataToIssue = createPresentationData(fileContent, options.generatorOptions); + const url = `${options.baseUrl}${options.presentationGenerator}`; + const axiosOptions = { + timeout: 2000, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `${options.oauthTokenType} ${options.oauthToken}` + } + } + try { + const response = await axios.post(url, dataToIssue, axiosOptions); + return response.data?.verifiablePresentation ? response.data.verifiablePresentation : {}; + } catch (error) { + throw new Error('Failed to get valid response'); + } +} + +async function generatePresentationFromBinary(file, options) { options = options || {}; const {stdout, stderr} = await exec(options.presentationGenerator + ' ' + options.generatorOptions + ' ' + path.join(__dirname, 'input', file)); @@ -78,6 +133,26 @@ const RFC3339regex = new RegExp('^(\\d{4})-(0[1-9]|1[0-2])-' + '(\\.[0-9]+)?(Z|(\\+|-)([01][0-9]|2[0-3]):' + '([0-5][0-9]))$', 'i'); +/** + * Transform a test input JSON-LD file to a payload for a REST credentials/issue + * @param {String} unsigned_jsonld A string of an unsigned credential JSON-LD + * @param {Object} options The arguments that should be passed to the VC generator + * @returns {String} A JSON-LD string to be used against REST APIs + */ +function createIssuanceData(unsigned_jsonld, options) { + return JSON.stringify({ credential: JSON.parse(unsigned_jsonld), options }); +} + +/** + * Transform a test input JSON-LD file to a payload for a REST presentation/prove + * @param {String} unsigned_jsonld A string of an unsigned presentation JSON-LD + * @param {String} options The arguments that should be passed to the VP generator + * @returns {String} A JSON-LD string to be used against REST APIs + */ +function createPresentationData(unsigned_jsonld, options) { + return JSON.stringify({ presentation: JSON.parse(unsigned_jsonld), options }); +} + module.exports = { generate, generatePresentation,