From 7237efd97f2fd11d96269d5102d2c6bd9bba9675 Mon Sep 17 00:00:00 2001 From: Mircea Nistor Date: Thu, 22 Feb 2024 18:22:57 +0100 Subject: [PATCH] fix(credential-w3c): forward DID resolution options to the resolver (#1344) fixes #1343 --- __tests__/localAgent.test.ts | 11 +++- __tests__/localJsonStoreAgent.test.ts | 13 +++- __tests__/restAgent.test.ts | 22 ++++--- __tests__/shared/verifiableDataLD.ts | 35 +++++++++++ packages/core-types/src/plugin.schema.ts | 60 +++++++++++++++++++ .../core-types/src/types/ICredentialIssuer.ts | 5 +- .../src/types/ICredentialStatusVerifier.ts | 3 +- .../src/types/ICredentialVerifier.ts | 19 +++++- .../src/agent/CredentialEIP712.ts | 22 +++++-- .../credential-eip712/src/plugin.schema.ts | 48 +++++++++++++++ .../src/types/ICredentialEIP712.ts | 9 +-- packages/credential-ld/src/action-handler.ts | 21 ++++--- .../credential-ld/src/ld-credential-module.ts | 33 ++++++---- packages/credential-ld/src/plugin.schema.ts | 48 +++++++++++++++ packages/credential-ld/src/types.ts | 9 +-- .../src/credential-status.ts | 2 +- packages/credential-w3c/src/action-handler.ts | 16 ++++- packages/did-comm/src/didcomm.ts | 36 +++++++---- packages/did-comm/src/plugin.schema.ts | 46 +++++++++++++- packages/did-comm/src/types/IDIDComm.ts | 7 ++- packages/did-comm/src/utils.ts | 13 +++- packages/test-react-app/src/veramo/setup.ts | 9 ++- packages/utils/src/did-utils.ts | 14 +++-- 23 files changed, 420 insertions(+), 81 deletions(-) diff --git a/__tests__/localAgent.test.ts b/__tests__/localAgent.test.ts index 25875099af..099c23d5cc 100644 --- a/__tests__/localAgent.test.ts +++ b/__tests__/localAgent.test.ts @@ -32,6 +32,8 @@ import { LdDefaultContexts, VeramoEcdsaSecp256k1RecoverySignature2020, VeramoEd25519Signature2018, + VeramoEd25519Signature2020, + VeramoJsonWebSignature2020, } from '../packages/credential-ld/src' import { EthrDIDProvider } from '../packages/did-provider-ethr/src' import { WebDIDProvider } from '../packages/did-provider-web/src' @@ -245,12 +247,17 @@ const setup = async (options?: IAgentOptions): Promise => { new SdrMessageHandler(), ], }), - new DIDComm({ transports: [new DIDCommHttpTransport()]}), + new DIDComm({ transports: [new DIDCommHttpTransport()] }), new CredentialPlugin(), new CredentialIssuerEIP712(), new CredentialIssuerLD({ contextMaps: [LdDefaultContexts, credential_contexts as any], - suites: [new VeramoEcdsaSecp256k1RecoverySignature2020(), new VeramoEd25519Signature2018()], + suites: [ + new VeramoEcdsaSecp256k1RecoverySignature2020(), + new VeramoEd25519Signature2018(), + new VeramoJsonWebSignature2020(), + new VeramoEd25519Signature2020(), + ], }), new SelectiveDisclosure(), new DIDDiscovery({ diff --git a/__tests__/localJsonStoreAgent.test.ts b/__tests__/localJsonStoreAgent.test.ts index 805448f71a..a4840faf01 100644 --- a/__tests__/localJsonStoreAgent.test.ts +++ b/__tests__/localJsonStoreAgent.test.ts @@ -30,6 +30,8 @@ import { LdDefaultContexts, VeramoEcdsaSecp256k1RecoverySignature2020, VeramoEd25519Signature2018, + VeramoEd25519Signature2020, + VeramoJsonWebSignature2020, } from '../packages/credential-ld/src' import { EthrDIDProvider } from '../packages/did-provider-ethr/src' import { WebDIDProvider } from '../packages/did-provider-web/src' @@ -51,7 +53,7 @@ import { PrivateKeyStoreJson, } from '../packages/data-store-json/src' import { FakeDidProvider, FakeDidResolver } from '../packages/test-utils/src' -import { PeerDIDProvider, getResolver as getDidPeerResolver } from '../packages/did-provider-peer/src' +import { getResolver as getDidPeerResolver, PeerDIDProvider } from '../packages/did-provider-peer/src' import { Resolver } from 'did-resolver' import { getResolver as ethrDidResolver } from 'ethr-did-resolver' @@ -77,7 +79,7 @@ import utils from './shared/utils' import { JsonFileStore } from './utils/json-file-store' import credentialStatus from './shared/credentialStatus' import credentialPluginTests from './shared/credentialPluginTests' -import dbInitOptions from "./shared/dbInitOptions"; +import dbInitOptions from './shared/dbInitOptions' jest.setTimeout(120000) @@ -205,7 +207,12 @@ const setup = async (options?: IAgentOptions): Promise => { new CredentialIssuerEIP712(), new CredentialIssuerLD({ contextMaps: [LdDefaultContexts, credential_contexts as any], - suites: [new VeramoEcdsaSecp256k1RecoverySignature2020(), new VeramoEd25519Signature2018()], + suites: [ + new VeramoEcdsaSecp256k1RecoverySignature2020(), + new VeramoEd25519Signature2018(), + new VeramoEd25519Signature2020(), + new VeramoJsonWebSignature2020(), + ], }), new SelectiveDisclosure(), ...(options?.plugins || []), diff --git a/__tests__/restAgent.test.ts b/__tests__/restAgent.test.ts index b4485a0df3..e00686adad 100644 --- a/__tests__/restAgent.test.ts +++ b/__tests__/restAgent.test.ts @@ -19,10 +19,7 @@ import { IResolver, TAgent, } from '../packages/core-types/src' -import { - Agent, - createAgent -} from '../packages/core/src' +import { Agent, createAgent } from '../packages/core/src' import { MessageHandler } from '../packages/message-handler/src' import { KeyManager } from '../packages/key-manager/src' import { AliasDiscoveryProvider, DIDManager } from '../packages/did-manager/src' @@ -41,13 +38,15 @@ import { LdDefaultContexts, VeramoEcdsaSecp256k1RecoverySignature2020, VeramoEd25519Signature2018, + VeramoEd25519Signature2020, + VeramoJsonWebSignature2020, } from '../packages/credential-ld/src' import { EthrDIDProvider } from '../packages/did-provider-ethr/src' import { WebDIDProvider } from '../packages/did-provider-web/src' import { getDidKeyResolver, KeyDIDProvider } from '../packages/did-provider-key/src' import { getDidPkhResolver, PkhDIDProvider } from '../packages/did-provider-pkh/src' import { getDidJwkResolver, JwkDIDProvider } from '../packages/did-provider-jwk/src' -import { getResolver as getDidPeerResolver, PeerDIDProvider } from "../packages/did-provider-peer/src"; +import { getResolver as getDidPeerResolver, PeerDIDProvider } from '../packages/did-provider-peer/src' import { DIDComm, DIDCommHttpTransport, DIDCommMessageHandler, IDIDComm } from '../packages/did-comm/src' import { ISelectiveDisclosure, @@ -99,7 +98,7 @@ import messageHandler from './shared/messageHandler' import didDiscovery from './shared/didDiscovery' import utils from './shared/utils' import credentialStatus from './shared/credentialStatus' -import credentialPluginTests from "./shared/credentialPluginTests"; +import credentialPluginTests from './shared/credentialPluginTests' jest.setTimeout(120000) @@ -197,7 +196,7 @@ const setup = async (options?: IAgentOptions): Promise => { defaultKms: 'local', }), 'did:peer': new PeerDIDProvider({ - defaultKms: 'local' + defaultKms: 'local', }), 'did:pkh': new PkhDIDProvider({ defaultKms: 'local', @@ -230,13 +229,18 @@ const setup = async (options?: IAgentOptions): Promise => { new SdrMessageHandler(), ], }), - new DIDComm({ transports: [new DIDCommHttpTransport()]}), + new DIDComm({ transports: [new DIDCommHttpTransport()] }), // intentionally use the deprecated name to test compatibility new CredentialIssuer(), new CredentialIssuerEIP712(), new CredentialIssuerLD({ contextMaps: [LdDefaultContexts, credential_contexts as any], - suites: [new VeramoEcdsaSecp256k1RecoverySignature2020(), new VeramoEd25519Signature2018()], + suites: [ + new VeramoEcdsaSecp256k1RecoverySignature2020(), + new VeramoEd25519Signature2018(), + new VeramoJsonWebSignature2020(), + new VeramoEd25519Signature2020(), + ], }), new SelectiveDisclosure(), new DIDDiscovery({ diff --git a/__tests__/shared/verifiableDataLD.ts b/__tests__/shared/verifiableDataLD.ts index 118e3892b6..059cdd487d 100644 --- a/__tests__/shared/verifiableDataLD.ts +++ b/__tests__/shared/verifiableDataLD.ts @@ -325,6 +325,41 @@ export default (testContext: { expect(result.verified).toBe(true) }) + it('should create and verify verifiable credential in LD with did:key Ed25519VerificationKey2020', async () => { + const iss = await agent.didManagerCreate({ provider: 'did:key', options: { keyType: 'Ed25519' } }) + const credential = await agent.createVerifiableCredential({ + credential: { + issuer: { id: iss.did }, + '@context': ['https://www.w3.org/2018/credentials/v1', 'https://veramo.io/contexts/profile/v1'], + type: ['VerifiableCredential', 'Profile'], + issuanceDate: new Date().toISOString(), + credentialSubject: { + id: didKeyIdentifier.did, + name: 'of the game', + }, + }, + proofFormat: 'lds', + resolutionOptions: { + publicKeyFormat: 'Ed25519VerificationKey2020', + }, + }) + + // Check credential: + expect(credential).toHaveProperty('proof') + const proofValue = credential.proof.jws ?? credential.proof.proofValue + expect(proofValue).toBeDefined() + + expect(credential.proof.type).toEqual('Ed25519Signature2020') + + const verification = await agent.verifyCredential({ + credential: credential, + resolutionOptions: { + publicKeyFormat: 'Ed25519VerificationKey2020', + }, + }) + expect(verification.verified).toBe(true) + }) + describe('credential verification policies', () => { it('can verify credential at a particular time', async () => { const issuanceDate = '2019-08-19T09:15:20.000Z' // 1566206120 diff --git a/packages/core-types/src/plugin.schema.ts b/packages/core-types/src/plugin.schema.ts index 45ce02b3f3..d3eae5cfbf 100644 --- a/packages/core-types/src/plugin.schema.ts +++ b/packages/core-types/src/plugin.schema.ts @@ -4218,6 +4218,18 @@ export const schema = { "ICreateVerifiableCredentialArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/CredentialPayload", "description": "The JSON payload of the Credential according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } \n\nThe signer of the Credential is chosen based on the `issuer.id` property of the `credential`\n\n`@context`, `type` and `issuanceDate` will be added automatically if omitted" @@ -4432,6 +4444,18 @@ export const schema = { "ICreateVerifiablePresentationArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "presentation": { "$ref": "#/components/schemas/PresentationPayload", "description": "The JSON payload of the Presentation according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } .\n\nThe signer of the Presentation is chosen based on the `holder` property of the `presentation`\n\n`@context`, `type` and `issuanceDate` will be added automatically if omitted" @@ -4788,6 +4812,18 @@ export const schema = { "IVerifyCredentialArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/W3CVerifiableCredential", "description": "The Verifiable Credential object according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } or the JWT representation.\n\nThe signer of the Credential is verified based on the `issuer.id` property of the `credential` or the `iss` property of the JWT payload respectively" @@ -5017,6 +5053,18 @@ export const schema = { "IVerifyPresentationArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "presentation": { "$ref": "#/components/schemas/W3CVerifiablePresentation", "description": "The Verifiable Presentation object according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } or the JWT representation.\n\nThe signer of the Presentation is verified based on the `holder` property of the `presentation` or the `iss` property of the JWT payload respectively" @@ -5152,6 +5200,18 @@ export const schema = { "ICheckCredentialStatusArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/VerifiableCredential", "description": "The credential whose status needs to be checked" diff --git a/packages/core-types/src/types/ICredentialIssuer.ts b/packages/core-types/src/types/ICredentialIssuer.ts index 9ce6d56e69..397e015e22 100644 --- a/packages/core-types/src/types/ICredentialIssuer.ts +++ b/packages/core-types/src/types/ICredentialIssuer.ts @@ -10,6 +10,7 @@ import { IDIDManager } from './IDIDManager.js' import { IDataStore } from './IDataStore.js' import { IKeyManager } from './IKeyManager.js' import { IIdentifier, IKey } from "./IIdentifier.js"; +import { UsingResolutionOptions } from './ICredentialVerifier.js' /** * The type of encoding to be used for the Verifiable Credential or Presentation to be generated. @@ -26,7 +27,7 @@ export type ProofFormat = 'jwt' | 'lds' | 'EthereumEip712Signature2021' * * @public */ -export interface ICreateVerifiablePresentationArgs { +export interface ICreateVerifiablePresentationArgs extends UsingResolutionOptions { /** * The JSON payload of the Presentation according to the * {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model}. @@ -97,7 +98,7 @@ export interface ICreateVerifiablePresentationArgs { * * @public */ -export interface ICreateVerifiableCredentialArgs { +export interface ICreateVerifiableCredentialArgs extends UsingResolutionOptions { /** * The JSON payload of the Credential according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} diff --git a/packages/core-types/src/types/ICredentialStatusVerifier.ts b/packages/core-types/src/types/ICredentialStatusVerifier.ts index 7b98bffbce..452c6a3d1d 100644 --- a/packages/core-types/src/types/ICredentialStatusVerifier.ts +++ b/packages/core-types/src/types/ICredentialStatusVerifier.ts @@ -2,6 +2,7 @@ import { DIDDocument } from 'did-resolver' import { IAgentContext, IPluginMethodMap } from './IAgent.js' import { VerifiableCredential, CredentialStatus } from './vc-data-model.js' import { IResolver } from './IResolver.js' +import { UsingResolutionOptions } from './ICredentialVerifier.js' /** * Arguments for calling {@link ICredentialStatusVerifier.checkCredentialStatus | checkCredentialStatus}. @@ -12,7 +13,7 @@ import { IResolver } from './IResolver.js' * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface ICheckCredentialStatusArgs { +export interface ICheckCredentialStatusArgs extends UsingResolutionOptions { /** * The credential whose status needs to be checked */ diff --git a/packages/core-types/src/types/ICredentialVerifier.ts b/packages/core-types/src/types/ICredentialVerifier.ts index e0c3ce8160..82944eb6de 100644 --- a/packages/core-types/src/types/ICredentialVerifier.ts +++ b/packages/core-types/src/types/ICredentialVerifier.ts @@ -3,6 +3,21 @@ import { IVerifyResult } from './IVerifyResult.js' import { W3CVerifiableCredential, W3CVerifiablePresentation } from './vc-data-model.js' import { IResolver } from './IResolver.js' import { IDIDManager } from './IDIDManager.js' +import { DIDResolutionOptions } from 'did-resolver' + +/** + * Options that are forwarded to the DID resolver. + * @public + */ +export interface UsingResolutionOptions { + /** + * Options to be passed to the DID resolver. + */ + resolutionOptions?: DIDResolutionOptions & { + // Used by did:key to determine the format of the public key. Specified here for discoverability. + publicKeyFormat?: string + } +} /** * Encapsulates the parameters required to verify a @@ -10,7 +25,7 @@ import { IDIDManager } from './IDIDManager.js' * * @public */ -export interface IVerifyCredentialArgs { +export interface IVerifyCredentialArgs extends UsingResolutionOptions { /** * The Verifiable Credential object according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} or the JWT representation. @@ -48,7 +63,7 @@ export interface IVerifyCredentialArgs { * * @public */ -export interface IVerifyPresentationArgs { +export interface IVerifyPresentationArgs extends UsingResolutionOptions { /** * The Verifiable Presentation object according to the * {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model} or the JWT representation. diff --git a/packages/credential-eip712/src/agent/CredentialEIP712.ts b/packages/credential-eip712/src/agent/CredentialEIP712.ts index 950b5083e3..ce9314144d 100644 --- a/packages/credential-eip712/src/agent/CredentialEIP712.ts +++ b/packages/credential-eip712/src/agent/CredentialEIP712.ts @@ -84,7 +84,12 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { keyRef = key.kid } - const extendedKeys = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context) + const extendedKeys = await mapIdentifierKeysToDoc( + identifier, + 'verificationMethod', + context, + args.resolutionOptions, + ) const extendedKey = extendedKeys.find((key) => key.kid === keyRef) if (!extendedKey) throw Error('key_not_found: The signing key is not available in the issuer DID document') @@ -147,7 +152,7 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { const verificationMessage = { ...signingInput, proof: verifyInputProof, - } + } const compat = { ...eip712Domain, @@ -177,7 +182,7 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { throw new Error('invalid_argument: credential.issuer must not be empty') } - const didDocument = await resolveDidOrThrow(issuer, context) + const didDocument = await resolveDidOrThrow(issuer, context, args.resolutionOptions) if (didDocument.verificationMethod) { for (const verificationMethod of didDocument.verificationMethod) { @@ -251,11 +256,16 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { keyRef = key.kid } - const extendedKeys = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context) + const extendedKeys = await mapIdentifierKeysToDoc( + identifier, + 'verificationMethod', + context, + args.resolutionOptions, + ) const extendedKey = extendedKeys.find((key) => key.kid === keyRef) if (!extendedKey) throw Error('key_not_found: The signing key is not available in the issuer DID document') - + let chainId try { chainId = getChainId(extendedKey.meta.verificationMethod) @@ -339,7 +349,7 @@ export class CredentialIssuerEIP712 implements IAgentPlugin { throw new Error('invalid_argument: args.presentation.issuer must not be empty') } - const didDocument = await resolveDidOrThrow(issuer, context) + const didDocument = await resolveDidOrThrow(issuer, context, args.resolutionOptions) if (didDocument.verificationMethod) { for (const verificationMethod of didDocument.verificationMethod) { diff --git a/packages/credential-eip712/src/plugin.schema.ts b/packages/credential-eip712/src/plugin.schema.ts index ca6be7ca19..e7bb6ebdc9 100644 --- a/packages/credential-eip712/src/plugin.schema.ts +++ b/packages/credential-eip712/src/plugin.schema.ts @@ -5,6 +5,18 @@ export const schema = { "ICreateVerifiableCredentialEIP712Args": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/CredentialPayload", "description": "The json payload of the Credential according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } \n\nThe signer of the Credential is chosen based on the `issuer.id` property of the `credential`\n\n`@context`, 'type' and 'issuanceDate' will be added automatically if omitted" @@ -189,6 +201,18 @@ export const schema = { "ICreateVerifiablePresentationEIP712Args": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "presentation": { "$ref": "#/components/schemas/PresentationPayload", "description": "The json payload of the Presentation according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } .\n\nThe signer of the Presentation is chosen based on the `holder` property of the `presentation`\n\n`@context`, `type` and `issuanceDate` will be added automatically if omitted" @@ -317,6 +341,18 @@ export const schema = { "IVerifyCredentialEIP712Args": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/VerifiableCredential", "description": "The json payload of the Credential according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } \n\nThe signer of the Credential is chosen based on the `issuer.id` property of the `credential`" @@ -330,6 +366,18 @@ export const schema = { "IVerifyPresentationEIP712Args": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "presentation": { "$ref": "#/components/schemas/VerifiablePresentation", "description": "The Verifiable Presentation object according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } or the JWT representation.\n\nThe signer of the Presentation is verified based on the `holder` property of the `presentation` or the `iss` property of the JWT payload respectively" diff --git a/packages/credential-eip712/src/types/ICredentialEIP712.ts b/packages/credential-eip712/src/types/ICredentialEIP712.ts index 9a5d4d5b47..4b9606418e 100644 --- a/packages/credential-eip712/src/types/ICredentialEIP712.ts +++ b/packages/credential-eip712/src/types/ICredentialEIP712.ts @@ -7,6 +7,7 @@ import { IPluginMethodMap, IResolver, PresentationPayload, + UsingResolutionOptions, VerifiableCredential, VerifiablePresentation, } from '@veramo/core-types' @@ -103,7 +104,7 @@ export interface ICredentialIssuerEIP712 extends IPluginMethodMap { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface ICreateVerifiableCredentialEIP712Args { +export interface ICreateVerifiableCredentialEIP712Args extends UsingResolutionOptions { /** * The json payload of the Credential according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} @@ -129,7 +130,7 @@ export interface ICreateVerifiableCredentialEIP712Args { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface ICreateVerifiablePresentationEIP712Args { +export interface ICreateVerifiablePresentationEIP712Args extends UsingResolutionOptions { /** * The json payload of the Presentation according to the * {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model}. @@ -154,7 +155,7 @@ export interface ICreateVerifiablePresentationEIP712Args { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface IVerifyCredentialEIP712Args { +export interface IVerifyCredentialEIP712Args extends UsingResolutionOptions { /** * The json payload of the Credential according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} @@ -172,7 +173,7 @@ export interface IVerifyCredentialEIP712Args { * * @public */ -export interface IVerifyPresentationEIP712Args { +export interface IVerifyPresentationEIP712Args extends UsingResolutionOptions { /** * The Verifiable Presentation object according to the * {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model} or the JWT representation. diff --git a/packages/credential-ld/src/action-handler.ts b/packages/credential-ld/src/action-handler.ts index 4e6dd8e0d2..7f41811911 100644 --- a/packages/credential-ld/src/action-handler.ts +++ b/packages/credential-ld/src/action-handler.ts @@ -37,6 +37,7 @@ import { IVerifyCredentialLDArgs, IVerifyPresentationLDArgs, } from './types.js' +import { DIDResolutionOptions } from 'did-resolver' const debug = Debug('veramo:credential-ld:action-handler') @@ -114,6 +115,7 @@ export class CredentialIssuerLD implements IAgentPlugin { context, identifier, args.keyRef, + args.resolutionOptions, ) let { now } = args @@ -169,6 +171,7 @@ export class CredentialIssuerLD implements IAgentPlugin { context, identifier, args.keyRef, + args.resolutionOptions, ) let { now } = args @@ -202,12 +205,7 @@ export class CredentialIssuerLD implements IAgentPlugin { now = new Date(now * 1000) } - return this.ldCredentialModule.verifyCredential( - credential, - args.fetchRemoteContexts || false, - { ...args, now }, - context, - ) + return this.ldCredentialModule.verifyCredential(credential, { ...args, now }, context) } /** {@inheritdoc ICredentialIssuerLD.verifyPresentationLD} */ @@ -224,7 +222,6 @@ export class CredentialIssuerLD implements IAgentPlugin { presentation, args.challenge, args.domain, - args.fetchRemoteContexts || false, { ...args, now }, context, ) @@ -234,8 +231,14 @@ export class CredentialIssuerLD implements IAgentPlugin { context: IAgentContext, identifier: IIdentifier, keyRef?: string, + resolutionOptions?: DIDResolutionOptions, ): Promise<{ signingKey: _ExtendedIKey; verificationMethodId: string }> { - const extendedKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc(identifier, 'assertionMethod', context) + const extendedKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc( + identifier, + 'assertionMethod', + context, + resolutionOptions, + ) let supportedTypes = this.ldCredentialModule.ldSuiteLoader.getAllSignatureSuiteTypes() let signingKey: _ExtendedIKey | undefined let verificationMethodId: string @@ -264,7 +267,7 @@ export class CredentialIssuerLD implements IAgentPlugin { /** * Returns true if the key is supported by any of the installed LD Signature suites - * @param k - the key to verify + * @param k - the key to match * * @internal */ diff --git a/packages/credential-ld/src/ld-credential-module.ts b/packages/credential-ld/src/ld-credential-module.ts index 364c999dbc..acaea3e995 100644 --- a/packages/credential-ld/src/ld-credential-module.ts +++ b/packages/credential-ld/src/ld-credential-module.ts @@ -4,6 +4,7 @@ import { IKey, IResolver, PresentationPayload, + UsingResolutionOptions, VerifiableCredential, VerifiablePresentation, } from '@veramo/core-types' @@ -19,6 +20,11 @@ import { RequiredAgentMethods } from './ld-suites.js' const debug = Debug('veramo:w3c:ld-credential-module') +type ForwardedOptions = UsingResolutionOptions & { + fetchRemoteContexts?: boolean // defaults to false + now?: number // defaults to Date.now() +} + export class LdCredentialModule { /** * TODO: General Implementation Notes @@ -36,13 +42,14 @@ export class LdCredentialModule { this.ldSuiteLoader = options.ldSuiteLoader } - getDocumentLoader(context: IAgentContext, attemptToFetchContexts: boolean = false) { + getDocumentLoader(context: IAgentContext, options?: ForwardedOptions) { return extendContextLoader(async (url: string) => { - // console.log(`resolving context for: ${url}`) + const resolutionOptions = { accept: 'application/did+ld+json', ...options?.resolutionOptions } + const attemptToFetchContexts = options?.fetchRemoteContexts ?? false // did resolution if (url.toLowerCase().startsWith('did:')) { - const resolutionResult = await context.agent.resolveDid({ didUrl: url }) + const resolutionResult = await context.agent.resolveDid({ didUrl: url, options: resolutionOptions }) const didDoc = resolutionResult.didDocument if (!didDoc) return @@ -107,7 +114,7 @@ export class LdCredentialModule { issuerDid: string, key: IKey, verificationMethodId: string, - options: any, + options: ForwardedOptions, context: IAgentContext, ): Promise { // TODO: try multiple matching suites until one works or list is exhausted @@ -115,7 +122,7 @@ export class LdCredentialModule { key.type, key.meta?.verificationMethod?.type ?? '', )[0] - const documentLoader = this.getDocumentLoader(context, options.fetchRemoteContexts) + const documentLoader = this.getDocumentLoader(context, options) // some suites can modify the incoming credential (e.g. add required contexts) suite.preSigningCredModification(credential) @@ -136,7 +143,7 @@ export class LdCredentialModule { verificationMethodId: string, challenge: string | undefined, domain: string | undefined, - options: any, + options: ForwardedOptions, context: IAgentContext, ): Promise { // TODO: try multiple matching suites until one works or list is exhausted @@ -144,7 +151,7 @@ export class LdCredentialModule { key.type, key.meta?.verificationMethod?.type ?? '', )[0] - const documentLoader = this.getDocumentLoader(context, options.fetchRemoteContexts) + const documentLoader = this.getDocumentLoader(context, options) suite.preSigningPresModification(presentation) @@ -161,15 +168,15 @@ export class LdCredentialModule { async verifyCredential( credential: VerifiableCredential, - fetchRemoteContexts: boolean = false, - options: any, + options: ForwardedOptions, context: IAgentContext, ): Promise { + const fetchRemoteContexts = options.fetchRemoteContexts ?? false const result = await vc.verifyCredential({ ...options, credential, suite: this.ldSuiteLoader.getAllSignatureSuites().map((x) => x.getSuiteForVerification()), - documentLoader: this.getDocumentLoader(context, fetchRemoteContexts), + documentLoader: this.getDocumentLoader(context, { ...options, fetchRemoteContexts }), compactProof: false, checkStatus: async () => Promise.resolve({ verified: true }), // Fake method }) @@ -186,15 +193,15 @@ export class LdCredentialModule { presentation: VerifiablePresentation, challenge: string | undefined, domain: string | undefined, - fetchRemoteContexts: boolean = false, - options: any, + options: ForwardedOptions, context: IAgentContext, ): Promise { + const fetchRemoteContexts = options.fetchRemoteContexts ?? false const result = await vc.verify({ ...options, presentation, suite: this.ldSuiteLoader.getAllSignatureSuites().map((x) => x.getSuiteForVerification()), - documentLoader: this.getDocumentLoader(context, fetchRemoteContexts), + documentLoader: this.getDocumentLoader(context, { ...options, fetchRemoteContexts }), challenge, domain, compactProof: false, diff --git a/packages/credential-ld/src/plugin.schema.ts b/packages/credential-ld/src/plugin.schema.ts index 2af50da873..bd73cd4e4a 100644 --- a/packages/credential-ld/src/plugin.schema.ts +++ b/packages/credential-ld/src/plugin.schema.ts @@ -5,6 +5,18 @@ export const schema = { "ICreateVerifiableCredentialLDArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/CredentialPayload", "description": "The json payload of the Credential according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } \n\nThe signer of the Credential is chosen based on the `issuer.id` property of the `credential`\n\n`@context`, `type` and `issuanceDate` will be added automatically if omitted" @@ -196,6 +208,18 @@ export const schema = { "ICreateVerifiablePresentationLDArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "presentation": { "$ref": "#/components/schemas/PresentationPayload", "description": "The json payload of the Presentation according to the\n {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model } .\n\nThe signer of the Presentation is chosen based on the `holder` property of the `presentation`\n\n`@context`, `type` and `issuanceDate` will be added automatically if omitted." @@ -339,6 +363,18 @@ export const schema = { "IVerifyCredentialLDArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "credential": { "$ref": "#/components/schemas/VerifiableCredential", "description": "The json payload of the Credential according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } \n\nThe signer of the Credential is chosen based on the `issuer.id` property of the `credential`" @@ -359,6 +395,18 @@ export const schema = { "IVerifyPresentationLDArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "presentation": { "$ref": "#/components/schemas/VerifiablePresentation", "description": "The json payload of the Credential according to the\n {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model } \n\nThe signer of the Credential is chosen based on the `issuer.id` property of the `credential`" diff --git a/packages/credential-ld/src/types.ts b/packages/credential-ld/src/types.ts index 4e8ac27449..8ec53c72a0 100644 --- a/packages/credential-ld/src/types.ts +++ b/packages/credential-ld/src/types.ts @@ -7,6 +7,7 @@ import { IPluginMethodMap, IResolver, PresentationPayload, + UsingResolutionOptions, VerifiableCredential, VerifiablePresentation, } from '@veramo/core-types' @@ -104,7 +105,7 @@ export interface ICredentialIssuerLD extends IPluginMethodMap { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface ICreateVerifiablePresentationLDArgs { +export interface ICreateVerifiablePresentationLDArgs extends UsingResolutionOptions { /** * The json payload of the Presentation according to the * {@link https://www.w3.org/TR/vc-data-model/#presentations | canonical model}. @@ -150,7 +151,7 @@ export interface ICreateVerifiablePresentationLDArgs { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface ICreateVerifiableCredentialLDArgs { +export interface ICreateVerifiableCredentialLDArgs extends UsingResolutionOptions { /** * The json payload of the Credential according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} @@ -186,7 +187,7 @@ export interface ICreateVerifiableCredentialLDArgs { * * @beta This API may change without a BREAKING CHANGE notice */ -export interface IVerifyCredentialLDArgs { +export interface IVerifyCredentialLDArgs extends UsingResolutionOptions { /** * The json payload of the Credential according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} @@ -216,7 +217,7 @@ export interface IVerifyCredentialLDArgs { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface IVerifyPresentationLDArgs { +export interface IVerifyPresentationLDArgs extends UsingResolutionOptions { /** * The json payload of the Credential according to the * {@link https://www.w3.org/TR/vc-data-model/#credentials | canonical model} diff --git a/packages/credential-status/src/credential-status.ts b/packages/credential-status/src/credential-status.ts index aa2c4dc6ca..3c3546b644 100644 --- a/packages/credential-status/src/credential-status.ts +++ b/packages/credential-status/src/credential-status.ts @@ -42,7 +42,7 @@ export class CredentialStatusPlugin implements IAgentPlugin { let didDoc = args.didDocumentOverride if (!didDoc) { const issuerDid = extractIssuer(args.credential) - didDoc = await resolveDidOrThrow(issuerDid, context) + didDoc = await resolveDidOrThrow(issuerDid, context, args.resolutionOptions) } const statusCheck: CredentialStatus = (await this.status.checkStatus( args.credential, diff --git a/packages/credential-w3c/src/action-handler.ts b/packages/credential-w3c/src/action-handler.ts index 7b5b63a7a1..acf20ada43 100644 --- a/packages/credential-w3c/src/action-handler.ts +++ b/packages/credential-w3c/src/action-handler.ts @@ -283,7 +283,13 @@ export class CredentialPlugin implements IAgentPlugin { if (type == DocumentFormat.JWT) { let jwt: string = typeof credential === 'string' ? credential : credential.proof.jwt - const resolver = { resolve: (didUrl: string) => context.agent.resolveDid({ didUrl }) } as Resolvable + const resolver = { + resolve: (didUrl: string) => + context.agent.resolveDid({ + didUrl, + options: otherOptions?.resolutionOptions, + }), + } as Resolvable try { // needs broader credential as well to check equivalence with jwt verificationResult = await verifyCredentialJWT(jwt, resolver, { @@ -398,7 +404,13 @@ export class CredentialPlugin implements IAgentPlugin { } else { jwt = presentation.proof.jwt } - const resolver = { resolve: (didUrl: string) => context.agent.resolveDid({ didUrl }) } as Resolvable + const resolver = { + resolve: (didUrl: string) => + context.agent.resolveDid({ + didUrl, + options: otherOptions?.resolutionOptions, + }), + } as Resolvable let audience = domain if (!audience) { diff --git a/packages/did-comm/src/didcomm.ts b/packages/did-comm/src/didcomm.ts index c8bf1fc654..a151da7586 100644 --- a/packages/did-comm/src/didcomm.ts +++ b/packages/did-comm/src/didcomm.ts @@ -19,6 +19,7 @@ import { } from 'did-jwt' import { type DIDDocument, + type DIDResolutionOptions, parse as parseDidUrl, type Service, type ServiceEndpoint, @@ -208,7 +209,12 @@ export class DIDComm implements IAgentPlugin { } // obtain sender signing key(s) from authentication section - const senderKeys = await mapIdentifierKeysToDoc(managedSender, 'authentication', context) + const senderKeys = await mapIdentifierKeysToDoc( + managedSender, + 'authentication', + context, + args.resolutionOptions, + ) // try to find a managed signing key that matches keyRef let signingKey = null if (isDefined(keyRef)) { @@ -277,7 +283,12 @@ export class DIDComm implements IAgentPlugin { // 1.1 check that args.message.from is a managed DID const sender: IIdentifier = await context.agent.didManagerGet({ did: args?.message?.from }) // 1.2 match key agreement keys from DID to managed keys - const senderKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc(sender, 'keyAgreement', context) + const senderKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc( + sender, + 'keyAgreement', + context, + args.resolutionOptions, + ) // try to find a sender key by keyRef, otherwise pick the first one let senderKey if (isDefined(keyRef)) { @@ -309,9 +320,12 @@ export class DIDComm implements IAgentPlugin { let recipients: IRecipient[] = [] - async function computeRecipients(to: string): Promise { + async function computeRecipients( + to: string, + resolutionOptions?: DIDResolutionOptions, + ): Promise { // 2.1 resolve DID for "to" - const didDocument: DIDDocument = await resolveDidOrThrow(to, context) + const didDocument: DIDDocument = await resolveDidOrThrow(to, context, resolutionOptions) // 2.2 extract all recipient key agreement keys and normalize them const keyAgreementKeys: _NormalizedVerificationMethod[] = ( @@ -461,11 +475,11 @@ export class DIDComm implements IAgentPlugin { ): Promise { const { msgObj, mediaType } = this.decodeMessageAndMediaType(args.message) if (mediaType === DIDCommMessageMediaType.SIGNED) { - return this.unpackDIDCommMessageJWS(msgObj as _DIDCommSignedMessage, context) + return this.unpackDIDCommMessageJWS(msgObj as _DIDCommSignedMessage, context, args.resolutionOptions) } else if (mediaType === DIDCommMessageMediaType.PLAIN) { return { message: msgObj, metaData: { packing: 'none' } } } else if (mediaType === DIDCommMessageMediaType.ENCRYPTED) { - return this.unpackDIDCommMessageJWE({ jwe: msgObj as JWE }, context) + return this.unpackDIDCommMessageJWE({ jwe: msgObj as JWE }, context, args.resolutionOptions) } else { throw Error('not_supported: ' + mediaType) } @@ -474,6 +488,7 @@ export class DIDComm implements IAgentPlugin { private async unpackDIDCommMessageJWS( jws: _DIDCommSignedMessage, context: IAgentContext, + resolutionOptions?: DIDResolutionOptions, ): Promise { // TODO: currently only supporting one signature const signatureEncoded: string = isDefined((<_FlattenedJWS>jws).signature) @@ -491,7 +506,7 @@ export class DIDComm implements IAgentPlugin { if (!isDefined(sender) || sender !== message.from) { throw new Error('invalid_jws: sender is not a DID or does not match the `kid`') } - const senderDoc = await resolveDidOrThrow(sender, context) + const senderDoc = await resolveDidOrThrow(sender, context, resolutionOptions) const senderKey = (await context.agent.getDIDComponentById({ didDocument: senderDoc, didUrl: header.kid, @@ -508,10 +523,11 @@ export class DIDComm implements IAgentPlugin { private async unpackDIDCommMessageJWE( { jwe }: { jwe: JWE }, context: IAgentContext, + resolutionOptions?: DIDResolutionOptions, ): Promise { // 0 resolve skid to DID doc // - find skid in DID doc and convert to 'X25519' byte array (if type matches) - let senderKeyBytes: Uint8Array | null = await extractSenderEncryptionKey(jwe, context) + let senderKeyBytes: Uint8Array | null = await extractSenderEncryptionKey(jwe, context, resolutionOptions) // 1. check whether kid is one of my DID URIs // - get recipient DID URIs @@ -531,7 +547,7 @@ export class DIDComm implements IAgentPlugin { // - filter to the keyAgreementKeys that match the recipient.kid // - match identifier.keys.publicKeyHex to (verificationMethod.publicKey*) // - return a list of `IKey` - const localKeys = await mapRecipientsToLocalKeys(managedRecipients, context) + const localKeys = await mapRecipientsToLocalKeys(managedRecipients, context, resolutionOptions) // 3. for each recipient // if isAuthcrypted? (if senderKey != null) @@ -714,7 +730,7 @@ export class DIDComm implements IAgentPlugin { throw new Error(`not_supported: return routes not supported yet`) } - const didDoc = await resolveDidOrThrow(recipientDidUrl, context) + const didDoc = await resolveDidOrThrow(recipientDidUrl, context, args.resolutionOptions) function processServiceObject(service: Service) { if (service.type === 'DIDCommMessaging') { diff --git a/packages/did-comm/src/plugin.schema.ts b/packages/did-comm/src/plugin.schema.ts index 94e504f235..e862c16739 100644 --- a/packages/did-comm/src/plugin.schema.ts +++ b/packages/did-comm/src/plugin.schema.ts @@ -26,6 +26,18 @@ export const schema = { "IPackDIDCommMessageArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "message": { "$ref": "#/components/schemas/IDIDCommMessage" }, @@ -205,6 +217,18 @@ export const schema = { "ISendDIDCommMessageArgs": { "type": "object", "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, "packedMessage": { "$ref": "#/components/schemas/IPackedDIDCommMessage" }, @@ -664,7 +688,27 @@ export const schema = { "deprecated": "Please use {@link IDIDComm.sendDIDCommMessage } instead. This will be removed in Veramo 4.0.\nInput arguments for {@link IDIDComm.sendMessageDIDCommAlpha1 }" }, "IUnpackDIDCommMessageArgs": { - "$ref": "#/components/schemas/IPackedDIDCommMessage", + "type": "object", + "properties": { + "resolutionOptions": { + "type": "object", + "properties": { + "publicKeyFormat": { + "type": "string" + }, + "accept": { + "type": "string" + } + }, + "description": "Options to be passed to the DID resolver." + }, + "message": { + "type": "string" + } + }, + "required": [ + "message" + ], "description": "The input to the {@link IDIDComm.unpackDIDCommMessage } method." }, "IUnpackedDIDCommMessage": { diff --git a/packages/did-comm/src/types/IDIDComm.ts b/packages/did-comm/src/types/IDIDComm.ts index 88803b658f..43cb8ff5fd 100644 --- a/packages/did-comm/src/types/IDIDComm.ts +++ b/packages/did-comm/src/types/IDIDComm.ts @@ -6,6 +6,7 @@ import { IMessageHandler, IPluginMethodMap, IResolver, + UsingResolutionOptions, } from '@veramo/core-types' import { ISendMessageDIDCommAlpha1Args } from '../didcomm.js' import { @@ -22,7 +23,7 @@ import { * * @beta This API may change without a BREAKING CHANGE notice. */ -export type IUnpackDIDCommMessageArgs = IPackedDIDCommMessage +export type IUnpackDIDCommMessageArgs = IPackedDIDCommMessage & UsingResolutionOptions /** * The input to the {@link IDIDComm.packDIDCommMessage} method. @@ -30,7 +31,7 @@ export type IUnpackDIDCommMessageArgs = IPackedDIDCommMessage * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface IPackDIDCommMessageArgs { +export interface IPackDIDCommMessageArgs extends UsingResolutionOptions { message: IDIDCommMessage packing: DIDCommMessagePacking keyRef?: string @@ -44,7 +45,7 @@ export interface IPackDIDCommMessageArgs { * * @beta This API may change without a BREAKING CHANGE notice. */ -export interface ISendDIDCommMessageArgs { +export interface ISendDIDCommMessageArgs extends UsingResolutionOptions { packedMessage: IPackedDIDCommMessage messageId: string returnTransportId?: string diff --git a/packages/did-comm/src/utils.ts b/packages/did-comm/src/utils.ts index d51bc3759a..64b7c22137 100644 --- a/packages/did-comm/src/utils.ts +++ b/packages/did-comm/src/utils.ts @@ -1,6 +1,6 @@ import { IAgentContext, IDIDManager, IIdentifier, IKeyManager, IResolver, TKeyType } from '@veramo/core-types' import { ECDH, JWE } from 'did-jwt' -import { parse as parseDidUrl } from 'did-resolver' +import { DIDResolutionOptions, parse as parseDidUrl } from 'did-resolver' import Debug from 'debug' import { @@ -31,11 +31,12 @@ export function createEcdhWrapper(secretKeyRef: string, context: IAgentContext, + resolutionOptions?: DIDResolutionOptions, ): Promise { let senderKey: Uint8Array | null = null const protectedHeader = decodeJoseBlob(jwe.protected) if (typeof protectedHeader.skid === 'string') { - const senderDoc = await resolveDidOrThrow(protectedHeader.skid, context) + const senderDoc = await resolveDidOrThrow(protectedHeader.skid, context, resolutionOptions) const sKey = (await context.agent.getDIDComponentById({ didDocument: senderDoc, didUrl: protectedHeader.skid, @@ -85,11 +86,17 @@ export async function extractManagedRecipients( export async function mapRecipientsToLocalKeys( managedKeys: { recipient: any; kid: string; identifier: IIdentifier }[], context: IAgentContext, + resolutionOptions?: DIDResolutionOptions, ): Promise<{ localKeyRef: string; recipient: any }[]> { const potentialKeys = await Promise.all( managedKeys.map(async ({ recipient, kid, identifier }) => { // TODO: use caching, since all recipients are supposed to belong to the same identifier - const identifierKeys = await mapIdentifierKeysToDoc(identifier, 'keyAgreement', context) + const identifierKeys = await mapIdentifierKeysToDoc( + identifier, + 'keyAgreement', + context, + resolutionOptions, + ) const localKey = identifierKeys.find((key) => key.meta.verificationMethod.id === kid) if (localKey) { return { localKeyRef: localKey.kid, recipient } diff --git a/packages/test-react-app/src/veramo/setup.ts b/packages/test-react-app/src/veramo/setup.ts index 4c471f952e..6a8f320095 100644 --- a/packages/test-react-app/src/veramo/setup.ts +++ b/packages/test-react-app/src/veramo/setup.ts @@ -27,6 +27,8 @@ import { LdDefaultContexts, VeramoEcdsaSecp256k1RecoverySignature2020, VeramoEd25519Signature2018, + VeramoEd25519Signature2020, + VeramoJsonWebSignature2020, } from '@veramo/credential-ld' import { getDidKeyResolver, KeyDIDProvider } from '@veramo/did-provider-key' import { getResolver as getDidPeerResolver, PeerDIDProvider } from '@veramo/did-provider-peer' @@ -150,7 +152,12 @@ export function getAgent(options?: IAgentOptions): TAgent { new CredentialPlugin(), new CredentialIssuerLD({ contextMaps: [LdDefaultContexts], - suites: [new VeramoEcdsaSecp256k1RecoverySignature2020(), new VeramoEd25519Signature2018()], + suites: [ + new VeramoEcdsaSecp256k1RecoverySignature2020(), + new VeramoEd25519Signature2018(), + new VeramoEd25519Signature2020(), + new VeramoJsonWebSignature2020(), + ], }), new SelectiveDisclosure(), ...(options?.plugins || []), diff --git a/packages/utils/src/did-utils.ts b/packages/utils/src/did-utils.ts index 6d84a0759c..c4dc5de4e3 100644 --- a/packages/utils/src/did-utils.ts +++ b/packages/utils/src/did-utils.ts @@ -1,6 +1,6 @@ -import { SigningKey, computeAddress } from 'ethers' +import { computeAddress, SigningKey } from 'ethers' import { DIDDocumentSection, IAgentContext, IIdentifier, IKey, IResolver } from '@veramo/core-types' -import { DIDDocument, VerificationMethod } from 'did-resolver' +import { DIDDocument, DIDResolutionOptions, VerificationMethod } from 'did-resolver' import { extractPublicKeyBytes } from 'did-jwt' import { _ExtendedIKey, @@ -171,7 +171,7 @@ export function getChainId(verificationMethod: _NormalizedVerificationMethod): n if (!Number.isInteger(result)) { throw new Error('chainId is not a number') } - if (result) { + if (result) { return result } throw new Error('blockchainAccountId does not include eip155 designation') @@ -187,6 +187,7 @@ export function getChainId(verificationMethod: _NormalizedVerificationMethod): n * `verificationMethod` to map all the keys. * @param context - the veramo agent context, which must contain a {@link @veramo/core-types#IResolver | IResolver} * implementation that can resolve the DID document of the identifier. + * @param resolutionOptions - optional parameters to be passed to the DID resolver * * @returns an array of mapped keys. The corresponding verification method is added to the `meta.verificationMethod` * property of the key. @@ -197,8 +198,9 @@ export async function mapIdentifierKeysToDoc( identifier: IIdentifier, section: DIDDocumentSection = 'keyAgreement', context: IAgentContext, + resolutionOptions?: DIDResolutionOptions, ): Promise<_ExtendedIKey[]> { - const didDocument = await resolveDidOrThrow(identifier.did, context) + const didDocument = await resolveDidOrThrow(identifier.did, context, resolutionOptions) // dereference all key agreement keys from DID document and normalize const documentKeys: _NormalizedVerificationMethod[] = await dereferenceDidKeys( didDocument, @@ -238,6 +240,7 @@ export async function mapIdentifierKeysToDoc( * @param didUrl - the DID to be resolved * @param context - the veramo agent context, which must contain a {@link @veramo/core-types#IResolver | IResolver} * implementation that can resolve the DID document of the `didUrl`. + * @param resolutionOptions - optional parameters to be passed to the DID resolver * * @returns a {@link did-resolver#DIDDocument | DIDDocument} if resolution is successful * @throws if the resolution fails @@ -247,9 +250,10 @@ export async function mapIdentifierKeysToDoc( export async function resolveDidOrThrow( didUrl: string, context: IAgentContext, + resolutionOptions?: DIDResolutionOptions, ): Promise { // TODO: add caching - const docResult = await context.agent.resolveDid({ didUrl: didUrl }) + const docResult = await context.agent.resolveDid({ didUrl: didUrl, options: resolutionOptions }) const err = docResult?.didResolutionMetadata?.error const msg = docResult?.didResolutionMetadata?.message const didDocument = docResult.didDocument