diff --git a/.gitignore b/.gitignore index 94b009c..fa2c3b5 100644 --- a/.gitignore +++ b/.gitignore @@ -118,4 +118,6 @@ dist .DS_Store # the keyv data store -src/data \ No newline at end of file +src/data + +compose-test.yaml \ No newline at end of file diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh new file mode 100644 index 0000000..ca2720e --- /dev/null +++ b/.husky/_/husky.sh @@ -0,0 +1,30 @@ +#!/bin/sh +if [ -z "$husky_skip_init" ]; then + debug () { + [ "$HUSKY_DEBUG" = "1" ] && echo "husky (debug) - $1" + } + + readonly hook_name="$(basename "$0")" + debug "starting $hook_name..." + + if [ "$HUSKY" = "0" ]; then + debug "HUSKY env variable is set to 0, skipping hook" + exit 0 + fi + + if [ -f ~/.huskyrc ]; then + debug "sourcing ~/.huskyrc" + . ~/.huskyrc + fi + + export readonly husky_skip_init=1 + sh -e "$0" "$@" + exitCode="$?" + + if [ $exitCode != 0 ]; then + echo "husky - $hook_name hook exited with code $exitCode (error)" + exit $exitCode + fi + + exit 0 +fi diff --git a/package.json b/package.json index 39fdc26..9cfdeb2 100644 --- a/package.json +++ b/package.json @@ -9,21 +9,15 @@ "test": "NODE_OPTIONS=--experimental-vm-modules npx mocha --timeout 10000 -r dotenv/config dotenv_config_path=src/test-fixtures/.env.testing src/app.test.js " }, "dependencies": { - "@digitalbazaar/did-io": "^2.0.0", - "@digitalbazaar/did-method-key": "^5.1.0", - "@digitalbazaar/ed25519-signature-2020": "^5.2.0", + "@digitalbazaar/ed25519-signature-2020": "^5.4.0", "@digitalbazaar/ed25519-verification-key-2020": "^4.1.0", - "@digitalbazaar/vc": "^6.0.1", + "@digitalbazaar/vc": "^7.0.0", + "@digitalcredentials/security-document-loader": "^6.0.0", "cookie-parser": "~1.4.4", "cors": "^2.8.5", - "credentials-context": "^2.0.0", - "crypto": "^1.0.1", "debug": "~2.6.9", - "did-context": "^3.1.1", "dotenv": "^16.0.3", - "ed25519-signature-2020-context": "^1.1.0", "express": "~4.16.1", - "jsonld-document-loader": "^2.0.0", "keyv": "^4.5.2", "keyv-file": "^0.2.0", "morgan": "~1.9.1" diff --git a/src/app.test.js b/src/app.test.js index 65b8734..5b37521 100644 --- a/src/app.test.js +++ b/src/app.test.js @@ -1,7 +1,8 @@ import { expect } from 'chai' import request from 'supertest'; import { build } from './app.js'; -import { getDataForExchangeSetupPost } from './test-fixtures/testData.js'; +import { getDataForExchangeSetupPost, testVC } from './test-fixtures/testData.js'; +import { getSignedDIDAuth } from './didAuth.js'; let app @@ -50,6 +51,43 @@ describe('api', () => { expect(response.body.length).to.eql(testData.data.length) }) + + it('returns array of wallet queries', async () => { + const testData = getDataForExchangeSetupPost('test') + const response = await request(app) + .post("/exchange") + .send(testData) + expect(response.header["content-type"]).to.have.string("json"); + expect(response.status).to.eql(200); + expect(response.body) + expect(response.body.length).to.eql(testData.data.length) + + const walletQuerys = response.body + const walletQuery = walletQuerys.find(q => q.retrievalId === 'someId') + const url = walletQuery.directDeepLink + + const parsedDeepLink = new URL(url) + const requestURI = parsedDeepLink.searchParams.get('vc_request_url'); //should be http://localhost:4004/exchange?challenge=VOclS8ZiMs&auth_type=bearer + // here we need to pull out just the path + // since we are calling the endpoint via + // supertest + const path = (new URL(requestURI)).pathname + const challenge = parsedDeepLink.searchParams.get('challenge'); // the challenge that the exchange service generated + const didAuth = await getSignedDIDAuth('did:ex:223234', challenge) + + const exchangeResponse = await request(app) + .post(path) + .send(didAuth) + + expect(exchangeResponse.header["content-type"]).to.have.string("json"); + expect(exchangeResponse.status).to.eql(200); + expect(exchangeResponse.body) + + const signedVC = exchangeResponse.body.vc + expect(signedVC).to.eql(testVC) + + }) + diff --git a/src/didAuth.js b/src/didAuth.js index 7dfac4c..5c8d6d3 100644 --- a/src/didAuth.js +++ b/src/didAuth.js @@ -1,12 +1,35 @@ -import {verify} from '@digitalbazaar/vc'; +import {verify,signPresentation, createPresentation} from '@digitalbazaar/vc'; import {Ed25519Signature2020} from '@digitalbazaar/ed25519-signature-2020'; -import { securityLoader } from './securityLoader.js'; +import { securityLoader } from '@digitalcredentials/security-document-loader'; +import {Ed25519VerificationKey2020} from '@digitalbazaar/ed25519-verification-key-2020'; const documentLoader = securityLoader().build() -const suite = new Ed25519Signature2020(); + +const key = await Ed25519VerificationKey2020.generate( + { + seed: new Uint8Array ([ + 217, 87, 166, 30, 75, 106, 132, 55, + 32, 120, 171, 23, 116, 73, 254, 74, + 230, 16, 127, 91, 2, 252, 224, 96, + 184, 172, 245, 157, 58, 217, 91, 240 + ]), + controller: "did:key:z6MkvL5yVCgPhYvQwSoSRQou6k6ZGfD5mNM57HKxufEXwfnP" + } +) + +const suite = new Ed25519Signature2020({key}); + +export const getSignedDIDAuth = async (holder = 'did:ex:12345', challenge) => { + const presentation = createPresentation({holder}); + return await signPresentation({ + presentation, suite, challenge, documentLoader + }); +} +const verificationSuite = new Ed25519Signature2020(); + export const verifyDIDAuth = async ({presentation, challenge}) => { - const result = await verify({presentation, challenge, suite, documentLoader}); + const result = await verify({presentation, challenge, suite: verificationSuite, documentLoader}); return result.verified } diff --git a/src/securityLoader.js b/src/securityLoader.js deleted file mode 100644 index 8dca752..0000000 --- a/src/securityLoader.js +++ /dev/null @@ -1,35 +0,0 @@ -import * as didKey from '@digitalbazaar/did-method-key'; -import didContext from 'did-context'; -import ed25519 from 'ed25519-signature-2020-context'; -import credentialsContext from 'credentials-context'; -import { JsonLdDocumentLoader } from 'jsonld-document-loader'; -import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020' -import { CachedResolver } from '@digitalbazaar/did-io'; - -const didKeyDriver = didKey.driver(); -didKeyDriver.use({ - multibaseMultikeyHeader: 'z6Mk', - fromMultibase: Ed25519VerificationKey2020.from -}); - -const resolver = new CachedResolver(); -resolver.use(didKeyDriver); - -export function securityLoader() { - - const staticLoader = new JsonLdDocumentLoader(); - - staticLoader.addStatic(ed25519.constants.CONTEXT_URL, - ed25519.contexts.get(ed25519.constants.CONTEXT_URL)); - - staticLoader.addStatic(didContext.constants.DID_CONTEXT_URL, - didContext.contexts.get(didContext.constants.DID_CONTEXT_URL)); - - staticLoader.addStatic(credentialsContext.constants.CREDENTIALS_CONTEXT_V1_URL, - credentialsContext.contexts.get(credentialsContext.constants.CREDENTIALS_CONTEXT_V1_URL)); - - staticLoader.setDidResolver(resolver); - - return staticLoader - -} diff --git a/src/test-fixtures/testData.js b/src/test-fixtures/testData.js index 7d4883e..22f230a 100644 --- a/src/test-fixtures/testData.js +++ b/src/test-fixtures/testData.js @@ -12,4 +12,4 @@ const getDataForExchangeSetupPost = (tenantName) => { return fakeData } -export { getDataForExchangeSetupPost } +export { getDataForExchangeSetupPost, testVC }