Skip to content

Commit

Permalink
feature: Add support to bind plugin methods to agent/other plugin met…
Browse files Browse the repository at this point in the history
…hod names. Allows to use multiple plugins that provide similar functionality
  • Loading branch information
nklomp committed Dec 2, 2021
1 parent 9166a31 commit a360378
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 51 deletions.
23 changes: 16 additions & 7 deletions packages/vc-handler-ld-local/agent.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
version: 3.0

constants:
baseUrl: http://localhost:3337
port: 3337
baseUrl: http://localhost:3339
port: 3339
# please use your own X25519 key, this is only an example
secretKey: 29739248cad1bd1a0fc4d9b75cd4d2990de535baf5caadfdf8d8f86664aa830c
methods:
- issueCredentialUsingLocalClient
- createVerifiableCredentialLDLocal
createVerifiablePresentationLDLocal
verifyPresentationLDLocal
verifyCredentialLDLocal

server:
baseUrl:
Expand Down Expand Up @@ -70,8 +73,14 @@ agent:
$args:
- schemaValidation: false
plugins:
- $require: ./packages/vc-handler-ld-local/dist#VcApiIssuer
- $require: '@veramo/credential-ld/build#VeramoLdSignature'
#
# - $require: '@veramo/credential-ld/build#CredentialIssuerLD'
# $args:
# - contextMaps: []
# suites: []
- $require: ./packages/vc-handler-ld-local/dist#CredentialHandlerLDLocal
$args:
- issueUrl: 'https://vc-api.sphereon.io/services/issue/credentials'
# please use your own authorization token, this is only an example
authorizationToken: 'ey...'
- contextMaps: []
suites: []
bindingOverrides: []
15 changes: 6 additions & 9 deletions packages/vc-handler-ld-local/src/__tests__/restAgent.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import 'cross-fetch/polyfill'
import { IAgent, createAgent, IAgentOptions } from '@veramo/core'
import { AgentRestClient } from '@veramo/remote-client'
import { IAgent } from '@veramo/core'
import express from 'express'
import { Server } from 'http'
import { AgentRouter, RequestWithAgentRouter } from '@veramo/remote-server'
import { getConfig } from '@veramo/cli/build/setup'
import { createObjects } from '@veramo/cli/build/lib/objectCreator'
import { ICredentialHandlerLDLocal } from '../index'
import vcApiIssuerAgentLogic from './shared/vcApiIssuerAgentLogic'
import { CredentialHandlerLDLocal } from '../index'
import { LdDefaultContexts, VeramoEd25519Signature2018 } from '@veramo/credential-ld'

jest.setTimeout(30000)

Expand Down Expand Up @@ -41,8 +38,9 @@ const getAgent = (options?: IAgentOptions) =>
*/

const setup = async (): Promise<boolean> => {
const config = getConfig('packages/vc-api-issuer/agent.yml')
config.agent.$args[0].plugins[0].$args[0].authorizationToken = process.env.VC_HTTP_API_AUTH_TOKEN
const config = getConfig('packages/vc-handler-ld-local/agent.yml');
(config.agent.$args[0].plugins[0].$args[0].contextMaps = [LdDefaultContexts /*, customContext*/]),
(config.agent.$args[0].plugins[0].$args[0].suites = [new VeramoEd25519Signature2018()])
const { agent } = createObjects(config, { agent: '/agent' })
serverAgent = agent

Expand All @@ -68,11 +66,10 @@ const tearDown = async (): Promise<boolean> => {
return true
}

const testContext = { /*getAgent, */setup, tearDown }
const testContext = { /*getAgent, */ setup, tearDown }

describe('REST integration tests', () => {
xit('handler', () => {
// vcApiIssuerAgentLogic(testContext)
})

})
Original file line number Diff line number Diff line change
@@ -1,15 +1,62 @@
import { TAgent } from '@veramo/core'
import { ICredentialHandlerLDLocal } from '../../types/ICredentialHandlerLDLocal'
import { CredentialHandlerLDLocal } from '../../agent/CredentialHandlerLDLocal'
import { Resolver } from 'did-resolver'
import { ContextDoc, LdDefaultContexts, VeramoEd25519Signature2018 } from '@veramo/credential-ld'
import { DIDManager, MemoryDIDStore } from '@veramo/did-manager'
import { createAgent, CredentialPayload, IDIDManager, IIdentifier, IKeyManager, IResolver, PresentationPayload, TAgent } from '@veramo/core'
import { KeyManagementSystem } from '@veramo/kms-local'
import { KeyManager, MemoryKeyStore, MemoryPrivateKeyStore } from '@veramo/key-manager'
import { CredentialIssuer, ICredentialIssuer } from '@veramo/credential-w3c'
import { getDidKeyResolver, KeyDIDProvider } from '@veramo/did-provider-key'
import { DIDResolverPlugin } from '@veramo/did-resolver'
import { getUniResolver } from '@sphereon/did-uni-client'
import { LtoDidProvider } from '../../../../lto-did-provider/src/lto-did-provider'
import { IDidConnectionMode } from '../../../../lto-did-provider/src/types/lto-provider-types'
import { ICredentialHandlerLDLocal, MethodNames } from '../../types/ICredentialHandlerLDLocal'

type ConfiguredAgent = TAgent<ICredentialHandlerLDLocal>

export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Promise<boolean>; tearDown: () => Promise<boolean> }) => {
describe('Issuer Agent Plugin', () => {
let agent: ConfiguredAgent

let didKeyIdentifier: IIdentifier
let didLtoIdentifier: IIdentifier
let agent: TAgent<IResolver & IKeyManager & IDIDManager & ICredentialIssuer & ICredentialHandlerLDLocal>

beforeAll(async () => {
await testContext.setup()
agent = testContext.getAgent()
agent = createAgent({
plugins: [
new KeyManager({
store: new MemoryKeyStore(),
kms: {
local: new KeyManagementSystem(new MemoryPrivateKeyStore()),
},
}),
new DIDManager({
providers: {
'did:key': new KeyDIDProvider({ defaultKms: 'local' })
},
store: new MemoryDIDStore(),
defaultProvider: 'did:key',
}),
new DIDResolverPlugin({
resolver: new Resolver({
...getDidKeyResolver(),
}),
}),
new CredentialIssuer(),
new CredentialHandlerLDLocal({
contextMaps: [LdDefaultContexts /*, customContext*/],
suites: [new VeramoEd25519Signature2018()],
bindingOverrides: new Map([
// Bindings to test overrides of credential-ld plugin methods
['createVerifiableCredentialLD', MethodNames.createVerifiableCredentialLDLocal],
['createVerifiablePresentationLD', MethodNames.createVerifiablePresentationLDLocal],
// We test the verify methods by using the LDLocal versions directly in the tests
]),
}),
],
})
didKeyIdentifier = await agent.didManagerCreate()
})

afterAll(async () => {
Expand All @@ -18,33 +65,21 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro
})

it('should issue', async () => {
const credential = {
'@context': [
'https://www.w3.org/2018/credentials/v1',
'https://www.w3.org/2018/credentials/examples/v1',
'https://w3id.org/vc-revocation-list-2020/v1',
],
credentialStatus: {
id: 'http://example.gov/credentials/3732#2',
type: 'RevocationList2020Status',
revocationListIndex: '2',
revocationListCredential: 'https://example.github.io/example-repo/revocation-credential.jsonld',
},
const credential ={
issuer: didKeyIdentifier.did,
type: ['VerifiableCredential', 'AlumniCredential'],
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://www.w3.org/2018/credentials/examples/v1'],
credentialSubject: {
degree: {
name: 'Bachelor of Science and Arts',
type: 'BachelorDegree',
id: didKeyIdentifier.did,
alumniOf: {
id: 'did:example:c276e12ec21ebfeb1f712ebc6f1',
name: 'Example University',
},
id: 'did:example:123',
},
id: 'http://example.gov/credentials/3732',
issuanceDate: '2020-03-16T22:37:26.544Z',
issuer: 'did:example:123',
type: ['VerifiableCredential', 'UniversityDegreeCredential'],
}

return await expect(
agent.issueCredentialUsingVcApi({
agent.createVerifiableCredentialLDLocal({
credential,
})
).resolves.not.toBeNull()
Expand Down
29 changes: 21 additions & 8 deletions packages/vc-handler-ld-local/src/agent/CredentialHandlerLDLocal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CredentialPayload, IAgentContext, IAgentPlugin, IIdentifier, IKey, IResolver, PresentationPayload } from '@veramo/core'

import { schema } from '../index'
import { IBindingOverrides, schema } from '../index'
import { ICredentialHandlerLDLocal, IRequiredContext } from '../types/ICredentialHandlerLDLocal'
import { VerifiableCredentialSP, VerifiablePresentationSP } from '@sphereon/ssi-sdk-core'
import {
Expand Down Expand Up @@ -37,23 +37,36 @@ export class CredentialHandlerLDLocal implements IAgentPlugin {
private ldCredentialModule: LdCredentialModule
readonly schema = schema.IVcLocalIssuerJsonLd
readonly methods: ICredentialHandlerLDLocal = {
// test: this.createVerifiableCredentialLDLocal.bind(this),
// We bind to existing methods as we can act as a drop in replacement. todo: Add config support for this mode
createVerifiableCredentialLD: this.createVerifiableCredentialLDLocal.bind(this),
createVerifiablePresentationLD: this.createVerifiablePresentationLDLocal.bind(this),
// createVerifiableCredentialLD: this.createVerifiableCredentialLDLocal.bind(this),
// createVerifiablePresentationLD: this.createVerifiablePresentationLDLocal.bind(this),
verifyPresentationLD: this.verifyPresentationLDLocal.bind(this),
verifyCredentialLD: this.verifyCredentialLDLocal.bind(this),

createVerifiableCredentialLDLocal: this.createVerifiableCredentialLDLocal.bind(this),
createVerifiablePresentationLDLocal: this.createVerifiablePresentationLDLocal.bind(this),
verifyPresentationLDLocal: this.verifyPresentationLDLocal.bind(this),
verifyCredentialLDLocal: this.verifyCredentialLDLocal.bind(this),
}

constructor(options: { contextMaps: RecordLike<OrPromise<ContextDoc>>[]; suites: VeramoLdSignature[] }) {
constructor(options: { contextMaps: RecordLike<OrPromise<ContextDoc>>[]; suites: VeramoLdSignature[]; bindingOverrides?: IBindingOverrides }) {
this.ldCredentialModule = new LdCredentialModule({
ldContextLoader: new LdContextLoader({ contextsPaths: options.contextMaps }),
ldSuiteLoader: new LdSuiteLoader({ veramoLdSignatures: options.suites }),
})

this.overrideBindings(options.bindingOverrides)
}

private overrideBindings(overrides?: IBindingOverrides) {
overrides?.forEach((methodName, bindingName) => {
if (typeof this[methodName] === 'function') {
this.methods[bindingName] = this[methodName].bind(this)
} else {
throw new Error(`Method ${methodName} supplied as target for ${bindingName} is not a valid method in CredentialHandlerLDLocal`)
}
console.log(`binding: this.${bindingName}() -> CredentialHandlerLDLocal.${methodName}()`)
})
}

/** {@inheritDoc ICredentialIssuerLDLocal.createVerifiableCredentialLDLocal} */
Expand Down Expand Up @@ -161,21 +174,21 @@ export class CredentialHandlerLDLocal implements IAgentPlugin {
/** {@inheritdoc ICredentialHandlerLDLocal.verifyCredentialLDLocal} */
public async verifyCredentialLDLocal(args: IVerifyCredentialLDArgs, context: IRequiredContext): Promise<boolean> {
const credential = args.credential
return this.ldCredentialModule.verifyCredential(credential, context)
return this.ldCredentialModule.verifyCredential(credential, context, args.fetchRemoteContexts)
}

/** {@inheritdoc ICredentialHandlerLDLocal.verifyPresentationLDLocal} */
public async verifyPresentationLDLocal(args: IVerifyPresentationLDArgs, context: IRequiredContext): Promise<boolean> {
const presentation = args.presentation
return this.ldCredentialModule.verifyPresentation(presentation, args.challenge, args.domain, context)
return this.ldCredentialModule.verifyPresentation(presentation, args.challenge, args.domain, context, args.fetchRemoteContexts)
}

private async findSigningKeyWithId(
context: IAgentContext<IResolver>,
identifier: IIdentifier,
keyRef?: string
): Promise<{ signingKey: IKey; verificationMethodId: string }> {
const extendedKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc(identifier, 'assertionMethod', context)
const extendedKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context)
let supportedTypes = this.ldCredentialModule.ldSuiteLoader.getAllSignatureSuiteTypes()
let signingKey: _ExtendedIKey | undefined
let verificationMethodId: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IAgentContext, IDIDManager, IKeyManager, IPluginMethodMap, IResolver } from '@veramo/core'
import { IAgentContext, IDIDManager, IKeyManager, IPluginMethod, IPluginMethodMap, IResolver } from '@veramo/core'
import { VerifiableCredentialSP, VerifiablePresentationSP } from '@sphereon/ssi-sdk-core'
import {
ICreateVerifiableCredentialLDArgs,
Expand All @@ -9,11 +9,27 @@ import {

export interface ICredentialHandlerLDLocal extends IPluginMethodMap {
createVerifiableCredentialLDLocal(args: ICreateVerifiableCredentialLDArgs, context: IRequiredContext): Promise<VerifiableCredentialSP>

createVerifiablePresentationLDLocal(args: ICreateVerifiablePresentationLDArgs, context: IRequiredContext): Promise<VerifiablePresentationSP>

verifyCredentialLDLocal(args: IVerifyCredentialLDArgs, context: IRequiredContext): Promise<boolean>

verifyPresentationLDLocal(args: IVerifyPresentationLDArgs, context: IRequiredContext): Promise<boolean>
}

/**
* Plugin method map interface
* @public
*/
export enum MethodNames {
createVerifiableCredentialLDLocal = 'createVerifiableCredentialLDLocal',
createVerifiablePresentationLDLocal = 'createVerifiablePresentationLDLocal',
verifyCredentialLDLocal = 'verifyCredentialLDLocal',
verifyPresentationLDLocal = 'verifyPresentationLDLocal',
}

export type IBindingOverrides = Map<string, MethodNames>

export enum events {
CREDENTIAL_ISSUED = 'credentialIssued',
}
Expand Down

0 comments on commit a360378

Please sign in to comment.