From 5a1a947c0246daaefa1d1911052b989e54c52796 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Tue, 10 Dec 2024 19:03:48 +0200 Subject: [PATCH 01/12] init discovery-protocol handler --- .eslintrc.js | 2 +- src/iden3comm/constants.ts | 9 +- src/iden3comm/handlers/discovery-protocol.ts | 105 ++++++++++++++++++ src/iden3comm/packageManager.ts | 13 +++ src/iden3comm/types/index.ts | 1 + src/iden3comm/types/packageManager.ts | 7 ++ .../types/protocol/discovery-protocol.ts | 34 ++++++ 7 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/iden3comm/handlers/discovery-protocol.ts create mode 100644 src/iden3comm/types/protocol/discovery-protocol.ts diff --git a/.eslintrc.js b/.eslintrc.js index 77fc6a3d..d536b3b9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,7 +10,7 @@ module.exports = { ...spellcheckerRule, cspell: { ...cspellConfig, - ignoreWords: ['unmarshal', 'JUvpllMEYUZ2joO59UNui_XYDqxVqiFLLAJ8klWuPBw', 'gdwj', 'fwor', 'multichain', "ETHWEI", "ETHGWEI"] + ignoreWords: ['unmarshal', 'JUvpllMEYUZ2joO59UNui_XYDqxVqiFLLAJ8klWuPBw', 'gdwj', 'fwor', 'multichain', "ETHWEI", "ETHGWEI", "didcomm"] } } ] diff --git a/src/iden3comm/constants.ts b/src/iden3comm/constants.ts index 398767f1..f061f6ab 100644 --- a/src/iden3comm/constants.ts +++ b/src/iden3comm/constants.ts @@ -1,6 +1,7 @@ import { AcceptProfile } from './types'; const IDEN3_PROTOCOL = 'https://iden3-communication.io/'; +const DIDCOMM_PROTOCOL = 'https://didcomm.org/'; /** * Constants for Iden3 protocol */ @@ -48,7 +49,13 @@ export const PROTOCOL_MESSAGE_TYPE = Object.freeze({ // PaymentRequestMessageType is type for payment-request message PAYMENT_REQUEST_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/0.1/payment-request` as const, // PaymentMessageType is type for payment message - PAYMENT_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/0.1/payment` as const + PAYMENT_MESSAGE_TYPE: `${IDEN3_PROTOCOL}credentials/0.1/payment` as const, + // DiscoveryProtocolQueriesMessageType is type for didcomm discovery protocol queries + DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE: + `${DIDCOMM_PROTOCOL}discover-features/2.0/queries` as const, + // DiscoveryProtocolDiscloseMessageType is type for didcomm discovery protocol disclose + DISCOVERY_PROTOCOL_DISCLOSE_MESSAGE_TYPE: + `${DIDCOMM_PROTOCOL}discover-features/2.0/disclose` as const }); /** diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts new file mode 100644 index 00000000..e3c472e8 --- /dev/null +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -0,0 +1,105 @@ +import { PROTOCOL_MESSAGE_TYPE } from '../constants'; + +import { BasicMessage, IPackageManager } from '../types'; + +import * as uuid from 'uuid'; +import { + DiscoverFeatureDiscloseMessage, + DiscoverFeatureQueriesMessage, + DiscoveryProtocolFeatureType +} from '../types/protocol/discovery-protocol'; +import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler'; + +/** + * RefreshHandlerOptions contains options for RefreshHandler + * @public + * @interface RefreshHandlerOptions + */ +export interface DiscoveryProtocolOptions { + packageManager: IPackageManager; +} + +/** + * Interface to work with discovery protocol handler + * + * @public + * @interface IDiscoveryProtocolHandler + */ +export interface IDiscoveryProtocolHandler { + /** + * handle discovery query message + * + * @param {DiscoverFeatureQueriesMessage} message - discover feature queries message + * @returns {Promise} - discover feature disclose message + */ + handleDiscoveryQuery( + message: DiscoverFeatureQueriesMessage + ): Promise; +} + +/** + * + * Handler for discovery protocol + * + * @public + * @beta + * @class DiscoveryProtocolHandler + * @implements implements DiscoveryProtocolHandler interface + */ +export class DiscoveryProtocolHandler + extends AbstractMessageHandler + implements IDiscoveryProtocolHandler, IProtocolMessageHandler +{ + /** + * Creates an instance of DiscoveryProtocolHandler. + * @param {DiscoveryProtocolOptions} _options - discovery protocol options + */ + constructor(private readonly _options: DiscoveryProtocolOptions) { + super(); + } + + /** + * @inheritdoc IProtocolMessageHandler#handle + */ + public async handle( + message: BasicMessage, + context: { [key: string]: unknown } + ): Promise { + switch (message.type) { + case PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE: + return await this.handleDiscoveryQuery(message as DiscoverFeatureQueriesMessage); + default: + return super.handle(message, context as { [key: string]: unknown }); + } + } + + /** + * @inheritdoc IDiscoveryProtocolHandler#handleDiscoveryQuery + */ + async handleDiscoveryQuery( + message: DiscoverFeatureQueriesMessage + ): Promise { + if (message.body.queries.length !== 1) { + throw new Error('Invalid number of queries. Only one query is supported'); + } + + if (message.body.queries[0]['feature-type'] !== DiscoveryProtocolFeatureType.Accept) { + throw new Error('Invalid feature-type. Only "accept" is supported'); + } + + const accept = this._options.packageManager.getSupportedProfiles(); + + return Promise.resolve({ + id: uuid.v4(), + type: PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_DISCLOSE_MESSAGE_TYPE, + body: { + disclosures: [ + { + 'feature-type': DiscoveryProtocolFeatureType.Accept, + accept + } + ] + } + }); + } +} diff --git a/src/iden3comm/packageManager.ts b/src/iden3comm/packageManager.ts index 2a73e1ca..40d7be48 100644 --- a/src/iden3comm/packageManager.ts +++ b/src/iden3comm/packageManager.ts @@ -21,6 +21,19 @@ export class PackageManager implements IPackageManager { this.packers = new Map(); } + /** {@inheritDoc IPackageManager.getSupportedProfiles} */ + getSupportedProfiles(): string[] { + const acceptProfiles: string[] = []; + const mediaTypes = this.getSupportedMediaTypes(); + for (const mediaType of mediaTypes) { + const p = this.packers.get(mediaType); + if (p) { + acceptProfiles.push(...p.getSupportedProfiles()); + } + } + return [...new Set(acceptProfiles)]; + } + /** {@inheritDoc IPackageManager.isProfileSupported} */ isProfileSupported(mediaType: MediaType, profile: string): boolean { const p = this.packers.get(mediaType); diff --git a/src/iden3comm/types/index.ts b/src/iden3comm/types/index.ts index da011009..b72df0ae 100644 --- a/src/iden3comm/types/index.ts +++ b/src/iden3comm/types/index.ts @@ -7,6 +7,7 @@ export * from './protocol/contract-request'; export * from './protocol/proposal-request'; export * from './protocol/payment'; export * from './protocol/accept-profile'; +export * from './protocol/discovery-protocol'; export * from './packer'; export * from './models'; diff --git a/src/iden3comm/types/packageManager.ts b/src/iden3comm/types/packageManager.ts index 554663bd..ddd43340 100644 --- a/src/iden3comm/types/packageManager.ts +++ b/src/iden3comm/types/packageManager.ts @@ -82,6 +82,13 @@ export interface IPackageManager { */ getSupportedMediaTypes(): MediaType[]; + /** + * gets supported accept profiles by packer manager + * + * @returns MediaType[] + */ + getSupportedProfiles(): string[]; + /** * returns true if media type and algorithms supported by packer manager * diff --git a/src/iden3comm/types/protocol/discovery-protocol.ts b/src/iden3comm/types/protocol/discovery-protocol.ts new file mode 100644 index 00000000..a42e51f8 --- /dev/null +++ b/src/iden3comm/types/protocol/discovery-protocol.ts @@ -0,0 +1,34 @@ +import { PROTOCOL_MESSAGE_TYPE } from '../../constants'; +import { BasicMessage } from '../packer'; + +/** @beta DiscoveryProtocolFeatureType is enum for supported feature-types */ +export enum DiscoveryProtocolFeatureType { + Accept = 'accept' +} + +/** @beta DiscoverFeatureQueriesMessage is struct the represents discover feature queries message */ +export type DiscoverFeatureQueriesMessage = BasicMessage & { + body: DiscoverFeatureQueriesBody; + type: typeof PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE; +}; + +/** @beta DiscoverFeatureQueriesBody is struct the represents discover feature queries body */ +export type DiscoverFeatureQueriesBody = { + queries: { + 'feature-type': DiscoveryProtocolFeatureType | string; + }[]; +}; + +/** @beta DiscoverFeatureDiscloseMessage is struct the represents discover feature disclose message */ +export type DiscoverFeatureDiscloseMessage = BasicMessage & { + body: DiscoverFeatureDiscloseBody; + type: typeof PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_DISCLOSE_MESSAGE_TYPE; +}; + +/** @beta DiscoverFeatureDiscloseBody is struct the represents discover feature disclose body */ +export type DiscoverFeatureDiscloseBody = { + disclosures: { + 'feature-type': DiscoveryProtocolFeatureType | string; + accept: Array; + }[]; +}; From c02122850dd476c8eb6a0aeb01921e23683c3a39 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Tue, 10 Dec 2024 19:51:37 +0200 Subject: [PATCH 02/12] fix expiration --- tests/handlers/payment.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/handlers/payment.test.ts b/tests/handlers/payment.test.ts index 27ee17cb..c198a8a6 100644 --- a/tests/handlers/payment.test.ts +++ b/tests/handlers/payment.test.ts @@ -458,7 +458,7 @@ describe('payment-request handler', () => { ], recipient: '0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a', amount: '2', - expirationDate: '2024-12-04T18:42:51.337Z', + expirationDate: '2124-12-10T17:25:18.907Z', nonce: '411393', metadata: '0x', proof: [ @@ -466,7 +466,7 @@ describe('payment-request handler', () => { type: SupportedPaymentProofType.EthereumEip712Signature2021, proofPurpose: 'assertionMethod', proofValue: - '0x6c6cbcc3943ab60f178f2721ccdcfa094b65196c0f0383e8bbf8747afce3fa0c64853872d705d5545f768fa54fa3cdafe4da37545d63ccda56f92ef9ff5ad4101b', + '0x31b57b1be0c22c21359252723a10b21c7c3e438705e1d46d2384feacdd8b429e3f1a3a230ac49fccdeef0aa1f7604020d4d4098c4078c4f24280c91c0dab45611b', verificationMethod: 'did:pkh:eip155:80002:0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a', created: new Date().toISOString(), eip712: { @@ -503,7 +503,7 @@ describe('payment-request handler', () => { tokenAddress: '0x71dcc8Dc5Eb138003d3571255458Bc5692a60eD4', recipient: '0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a', amount: '2', - expirationDate: '2024-12-04T18:43:31.082Z', + expirationDate: '2124-12-10T17:25:18.907Z', nonce: '411393', metadata: '0x', proof: [ @@ -511,7 +511,7 @@ describe('payment-request handler', () => { type: SupportedPaymentProofType.EthereumEip712Signature2021, proofPurpose: 'assertionMethod', proofValue: - '0xeb1e1d485ba8149c43b391bcadf4afb26f5b3e6cd66724c48ba10abb67c20c9158abf6efeb3a67b340f6bc9302d44bb47cfa0e1918c9cd382e18da154c4bfd011b', + '0x2b355fbeb6f303ebf3c5a88b335129799c67fa5db3debee8ee265b4d46fbeb7349a1b22e4c012d8a3c48581f8d77d8888337f5f0c9b7a38a0a7869749173937f1b', verificationMethod: 'did:pkh:eip155:80002:0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a', created: new Date().toISOString(), eip712: { From f7f0b1080829f326e6e9ddc78ba060a247d0863d Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Wed, 11 Dec 2024 15:28:30 +0200 Subject: [PATCH 03/12] add unit tests --- src/iden3comm/handlers/discovery-protocol.ts | 92 +++++++++++--- src/iden3comm/handlers/index.ts | 1 + .../types/protocol/discovery-protocol.ts | 11 +- tests/handlers/discover-protocol.test.ts | 112 ++++++++++++++++++ 4 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 tests/handlers/discover-protocol.test.ts diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index e3c472e8..e808f063 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -5,20 +5,86 @@ import { BasicMessage, IPackageManager } from '../types'; import * as uuid from 'uuid'; import { DiscoverFeatureDiscloseMessage, + DiscoverFeatureDisclosure, DiscoverFeatureQueriesMessage, DiscoveryProtocolFeatureType } from '../types/protocol/discovery-protocol'; import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler'; /** - * RefreshHandlerOptions contains options for RefreshHandler + * DiscoveryProtocolOptions contains options for DiscoveryProtocolHandler * @public - * @interface RefreshHandlerOptions + * @interface DiscoveryProtocolOptions */ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; } +/** + * @beta + * createDiscoveryFeatureQueryMessage is a function to create didcomm protocol discovery-feature query message + * @param opts - discovery-feature query options + * @returns `DiscoverFeatureQueriesMessage` + */ +export function createDiscoveryFeatureQueryMessage(opts?: { + featureTypes?: (DiscoveryProtocolFeatureType | string)[]; + from?: string; + to?: string; + created_time?: number; + expires_time?: number; +}): DiscoverFeatureQueriesMessage { + const uuidv4 = uuid.v4(); + return { + id: uuidv4, + thid: uuidv4, + type: PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE, + body: { + queries: opts?.featureTypes?.length + ? opts.featureTypes.map((featureType) => ({ 'feature-type': featureType })) + : [ + { + 'feature-type': DiscoveryProtocolFeatureType.Accept + } + ] + }, + from: opts?.from, + to: opts?.to, + created_time: opts?.created_time, + expires_time: opts?.expires_time + }; +} + +/** + * @beta + * createDiscoveryFeatureDiscloseMessage is a function to create didcomm protocol discovery-feature disclose message + * @param {DiscoverFeatureDisclosure[]} disclosures - array of disclosures + * @param opts - basic message options + * @returns `DiscoverFeatureQueriesMessage` + */ +export function createDiscoveryFeatureDiscloseMessage( + disclosures: DiscoverFeatureDisclosure[], + opts?: { + from?: string; + to?: string; + created_time?: number; + expires_time?: number; + } +): DiscoverFeatureDiscloseMessage { + const uuidv4 = uuid.v4(); + return { + id: uuidv4, + thid: uuidv4, + type: PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_DISCLOSE_MESSAGE_TYPE, + body: { + disclosures + }, + from: opts?.from, + to: opts?.to, + created_time: opts?.created_time, + expires_time: opts?.expires_time + }; +} + /** * Interface to work with discovery protocol handler * @@ -87,19 +153,15 @@ export class DiscoveryProtocolHandler throw new Error('Invalid feature-type. Only "accept" is supported'); } - const accept = this._options.packageManager.getSupportedProfiles(); - - return Promise.resolve({ - id: uuid.v4(), - type: PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_DISCLOSE_MESSAGE_TYPE, - body: { - disclosures: [ - { - 'feature-type': DiscoveryProtocolFeatureType.Accept, - accept - } - ] + const disclosures = [ + { + 'feature-type': DiscoveryProtocolFeatureType.Accept, + accept: this._options.packageManager.getSupportedProfiles() } - }); + ]; + + return Promise.resolve( + createDiscoveryFeatureDiscloseMessage(disclosures, { to: message.from, from: message.to }) + ); } } diff --git a/src/iden3comm/handlers/index.ts b/src/iden3comm/handlers/index.ts index 5a718b16..fbeb9918 100644 --- a/src/iden3comm/handlers/index.ts +++ b/src/iden3comm/handlers/index.ts @@ -7,3 +7,4 @@ export * from './common'; export * from './credential-proposal'; export * from './message-handler'; export * from './payment'; +export * from './discovery-protocol'; diff --git a/src/iden3comm/types/protocol/discovery-protocol.ts b/src/iden3comm/types/protocol/discovery-protocol.ts index a42e51f8..91e89b5d 100644 --- a/src/iden3comm/types/protocol/discovery-protocol.ts +++ b/src/iden3comm/types/protocol/discovery-protocol.ts @@ -27,8 +27,11 @@ export type DiscoverFeatureDiscloseMessage = BasicMessage & { /** @beta DiscoverFeatureDiscloseBody is struct the represents discover feature disclose body */ export type DiscoverFeatureDiscloseBody = { - disclosures: { - 'feature-type': DiscoveryProtocolFeatureType | string; - accept: Array; - }[]; + disclosures: DiscoverFeatureDisclosure[]; +}; + +/** @beta DiscoverFeatureDisclosure is struct the represents discover feature disclosure */ +export type DiscoverFeatureDisclosure = { + 'feature-type': DiscoveryProtocolFeatureType | string; + accept: Array; }; diff --git a/tests/handlers/discover-protocol.test.ts b/tests/handlers/discover-protocol.test.ts new file mode 100644 index 00000000..dcb4ec78 --- /dev/null +++ b/tests/handlers/discover-protocol.test.ts @@ -0,0 +1,112 @@ +import { expect } from 'chai'; +import { + DiscoverFeatureQueriesMessage, + IPackageManager, + JWSPacker, + KMS, + PackageManager, + PlainPacker, + ZKPPacker +} from '../../src'; +import { + DiscoveryProtocolHandler, + createDiscoveryFeatureQueryMessage +} from '../../src/iden3comm/handlers/discovery-protocol'; +import { DIDResolutionResult } from 'did-resolver'; + +describe('discovery-protocol', () => { + let discoveryFeatureQueryMessage: DiscoverFeatureQueriesMessage; + let jwsPacker: JWSPacker; + let zkpPacker: ZKPPacker; + let plainPacker: PlainPacker; + + beforeEach(async () => { + jwsPacker = new JWSPacker(new KMS(), { + resolve: () => Promise.resolve({ didDocument: {} } as DIDResolutionResult) + }); + + zkpPacker = new ZKPPacker(new Map(), new Map()); + plainPacker = new PlainPacker(); + discoveryFeatureQueryMessage = createDiscoveryFeatureQueryMessage(); + }); + + it('plain message accept disclosures', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([plainPacker]); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); + expect(disclosures.length).to.be.eq(1); + expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0].accept.length).to.be.eq(1); + expect(disclosures[0].accept[0]).to.be.eq('env=application/iden3comm-plain-json'); + }); + + it('jws and plain message accept disclosures', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([new PlainPacker(), plainPacker, jwsPacker]); + + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); + expect(disclosures.length).to.be.eq(1); + + expect(disclosures[0].accept.length).to.be.eq(2); + expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); + expect(disclosures[0].accept).to.include( + 'env=application/iden3comm-signed-json&alg=ES256K,ES256K-R' + ); + }); + + it('zkp and plain message accept disclosures', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([new PlainPacker(), plainPacker, zkpPacker]); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); + expect(disclosures.length).to.be.eq(1); + + expect(disclosures[0].accept.length).to.be.eq(2); + expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); + expect(disclosures[0].accept).to.include( + 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' + ); + }); + + it('zkp, jws and plain message accept disclosures', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([new PlainPacker(), plainPacker, zkpPacker, jwsPacker]); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); + expect(disclosures.length).to.be.eq(1); + + expect(disclosures[0].accept.length).to.be.eq(3); + expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); + expect(disclosures[0].accept).to.include( + 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' + ); + expect(disclosures[0].accept).to.include( + 'env=application/iden3comm-signed-json&alg=ES256K,ES256K-R' + ); + }); +}); From fd30c0b194231f5d8540789f134a02c5ce07fce2 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Wed, 11 Dec 2024 15:41:18 +0200 Subject: [PATCH 04/12] fix createDate and add expires time --- src/iden3comm/handlers/discovery-protocol.ts | 27 ++++++++++++++------ src/iden3comm/types/packageManager.ts | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index e808f063..6223538f 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -10,6 +10,7 @@ import { DiscoveryProtocolFeatureType } from '../types/protocol/discovery-protocol'; import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler'; +import { getUnixTimestamp } from '@iden3/js-iden3-core'; /** * DiscoveryProtocolOptions contains options for DiscoveryProtocolHandler @@ -18,6 +19,7 @@ import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handl */ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; + disclosureExpires?: Date; } /** @@ -30,7 +32,6 @@ export function createDiscoveryFeatureQueryMessage(opts?: { featureTypes?: (DiscoveryProtocolFeatureType | string)[]; from?: string; to?: string; - created_time?: number; expires_time?: number; }): DiscoverFeatureQueriesMessage { const uuidv4 = uuid.v4(); @@ -49,7 +50,7 @@ export function createDiscoveryFeatureQueryMessage(opts?: { }, from: opts?.from, to: opts?.to, - created_time: opts?.created_time, + created_time: getUnixTimestamp(new Date()), expires_time: opts?.expires_time }; } @@ -66,7 +67,6 @@ export function createDiscoveryFeatureDiscloseMessage( opts?: { from?: string; to?: string; - created_time?: number; expires_time?: number; } ): DiscoverFeatureDiscloseMessage { @@ -80,7 +80,7 @@ export function createDiscoveryFeatureDiscloseMessage( }, from: opts?.from, to: opts?.to, - created_time: opts?.created_time, + created_time: getUnixTimestamp(new Date()), expires_time: opts?.expires_time }; } @@ -96,10 +96,14 @@ export interface IDiscoveryProtocolHandler { * handle discovery query message * * @param {DiscoverFeatureQueriesMessage} message - discover feature queries message + * @param {{ expires_time?: number}} opts - discover feature handle options * @returns {Promise} - discover feature disclose message */ handleDiscoveryQuery( - message: DiscoverFeatureQueriesMessage + message: DiscoverFeatureQueriesMessage, + opts?: { + expires_time?: number; + } ): Promise; } @@ -133,7 +137,7 @@ export class DiscoveryProtocolHandler ): Promise { switch (message.type) { case PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE: - return await this.handleDiscoveryQuery(message as DiscoverFeatureQueriesMessage); + return await this.handleDiscoveryQuery(message as DiscoverFeatureQueriesMessage, context); default: return super.handle(message, context as { [key: string]: unknown }); } @@ -143,7 +147,10 @@ export class DiscoveryProtocolHandler * @inheritdoc IDiscoveryProtocolHandler#handleDiscoveryQuery */ async handleDiscoveryQuery( - message: DiscoverFeatureQueriesMessage + message: DiscoverFeatureQueriesMessage, + opts?: { + expires_time?: number; + } ): Promise { if (message.body.queries.length !== 1) { throw new Error('Invalid number of queries. Only one query is supported'); @@ -161,7 +168,11 @@ export class DiscoveryProtocolHandler ]; return Promise.resolve( - createDiscoveryFeatureDiscloseMessage(disclosures, { to: message.from, from: message.to }) + createDiscoveryFeatureDiscloseMessage(disclosures, { + to: message.from, + from: message.to, + expires_time: opts?.expires_time + }) ); } } diff --git a/src/iden3comm/types/packageManager.ts b/src/iden3comm/types/packageManager.ts index ddd43340..25f9d137 100644 --- a/src/iden3comm/types/packageManager.ts +++ b/src/iden3comm/types/packageManager.ts @@ -85,7 +85,7 @@ export interface IPackageManager { /** * gets supported accept profiles by packer manager * - * @returns MediaType[] + * @returns string[] */ getSupportedProfiles(): string[]; From c1ef3389023c32b729c3bbb9d8267aa569441775 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Wed, 11 Dec 2024 15:41:43 +0200 Subject: [PATCH 05/12] rm --- src/iden3comm/handlers/discovery-protocol.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index 6223538f..e4bee6c1 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -19,7 +19,6 @@ import { getUnixTimestamp } from '@iden3/js-iden3-core'; */ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; - disclosureExpires?: Date; } /** From e3eb4db014cf97d75b4428cf9e68ecdfff0ec6f7 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Wed, 11 Dec 2024 15:45:29 +0200 Subject: [PATCH 06/12] add BasicHandlerOptions --- src/iden3comm/handlers/discovery-protocol.ts | 34 +++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index e4bee6c1..084e4203 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -9,8 +9,13 @@ import { DiscoverFeatureQueriesMessage, DiscoveryProtocolFeatureType } from '../types/protocol/discovery-protocol'; -import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler'; +import { + AbstractMessageHandler, + BasicHandlerOptions, + IProtocolMessageHandler +} from './message-handler'; import { getUnixTimestamp } from '@iden3/js-iden3-core'; +import { verifyExpiresTime } from './common'; /** * DiscoveryProtocolOptions contains options for DiscoveryProtocolHandler @@ -21,6 +26,17 @@ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; } +/** + * + * Options to pass to discovery-protocol handler + * + * @public + * @interface DiscoveryProtocolHandlerOptions + */ +export type DiscoveryProtocolHandlerOptions = BasicHandlerOptions & { + disclosureExpiresDate?: Date; +}; + /** * @beta * createDiscoveryFeatureQueryMessage is a function to create didcomm protocol discovery-feature query message @@ -100,9 +116,7 @@ export interface IDiscoveryProtocolHandler { */ handleDiscoveryQuery( message: DiscoverFeatureQueriesMessage, - opts?: { - expires_time?: number; - } + opts?: DiscoveryProtocolHandlerOptions ): Promise; } @@ -147,10 +161,12 @@ export class DiscoveryProtocolHandler */ async handleDiscoveryQuery( message: DiscoverFeatureQueriesMessage, - opts?: { - expires_time?: number; - } + opts?: DiscoveryProtocolHandlerOptions ): Promise { + if (!opts?.allowExpiredMessages) { + verifyExpiresTime(message); + } + if (message.body.queries.length !== 1) { throw new Error('Invalid number of queries. Only one query is supported'); } @@ -170,7 +186,9 @@ export class DiscoveryProtocolHandler createDiscoveryFeatureDiscloseMessage(disclosures, { to: message.from, from: message.to, - expires_time: opts?.expires_time + expires_time: opts?.disclosureExpiresDate + ? getUnixTimestamp(opts.disclosureExpiresDate) + : undefined }) ); } From c823c9188cb31a3713fccec475426f9c32037819 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Wed, 11 Dec 2024 15:46:42 +0200 Subject: [PATCH 07/12] add @beta --- src/iden3comm/handlers/discovery-protocol.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index 084e4203..ea21e50e 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -18,6 +18,7 @@ import { getUnixTimestamp } from '@iden3/js-iden3-core'; import { verifyExpiresTime } from './common'; /** + * @beta * DiscoveryProtocolOptions contains options for DiscoveryProtocolHandler * @public * @interface DiscoveryProtocolOptions @@ -30,8 +31,9 @@ export interface DiscoveryProtocolOptions { * * Options to pass to discovery-protocol handler * + * @beta * @public - * @interface DiscoveryProtocolHandlerOptions + * @type DiscoveryProtocolHandlerOptions */ export type DiscoveryProtocolHandlerOptions = BasicHandlerOptions & { disclosureExpiresDate?: Date; @@ -103,6 +105,7 @@ export function createDiscoveryFeatureDiscloseMessage( /** * Interface to work with discovery protocol handler * + * @beta * @public * @interface IDiscoveryProtocolHandler */ From cda7ec73574b614ff96f1232a77faf981f8f1503 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Fri, 13 Dec 2024 17:59:31 +0200 Subject: [PATCH 08/12] resolve comments --- package-lock.json | 4 ++-- package.json | 2 +- src/iden3comm/handlers/discovery-protocol.ts | 16 +++++++++++----- .../types/protocol/discovery-protocol.ts | 9 +++++++-- tests/handlers/discover-protocol.test.ts | 9 +++++---- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2d0cd514..39f2a423 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@0xpolygonid/js-sdk", - "version": "1.25.0", + "version": "1.26.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@0xpolygonid/js-sdk", - "version": "1.25.0", + "version": "1.26.0", "license": "MIT or Apache-2.0", "dependencies": { "@iden3/onchain-non-merklized-issuer-base-abi": "^0.0.3", diff --git a/package.json b/package.json index 85d7a277..1d910f0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xpolygonid/js-sdk", - "version": "1.25.0", + "version": "1.26.0", "description": "SDK to work with Polygon ID", "main": "dist/node/cjs/index.js", "module": "dist/node/esm/index.js", diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index ea21e50e..06aca696 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -7,6 +7,7 @@ import { DiscoverFeatureDiscloseMessage, DiscoverFeatureDisclosure, DiscoverFeatureQueriesMessage, + DiscoverFeatureQueryType, DiscoveryProtocolFeatureType } from '../types/protocol/discovery-protocol'; import { @@ -46,7 +47,7 @@ export type DiscoveryProtocolHandlerOptions = BasicHandlerOptions & { * @returns `DiscoverFeatureQueriesMessage` */ export function createDiscoveryFeatureQueryMessage(opts?: { - featureTypes?: (DiscoveryProtocolFeatureType | string)[]; + featureTypes?: DiscoveryProtocolFeatureType[]; from?: string; to?: string; expires_time?: number; @@ -58,10 +59,12 @@ export function createDiscoveryFeatureQueryMessage(opts?: { type: PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE, body: { queries: opts?.featureTypes?.length - ? opts.featureTypes.map((featureType) => ({ 'feature-type': featureType })) + ? opts.featureTypes.map((featureType) => ({ + [DiscoverFeatureQueryType.FeatureType]: featureType + })) : [ { - 'feature-type': DiscoveryProtocolFeatureType.Accept + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept } ] }, @@ -174,13 +177,16 @@ export class DiscoveryProtocolHandler throw new Error('Invalid number of queries. Only one query is supported'); } - if (message.body.queries[0]['feature-type'] !== DiscoveryProtocolFeatureType.Accept) { + if ( + message.body.queries[0][DiscoverFeatureQueryType.FeatureType] !== + DiscoveryProtocolFeatureType.Accept + ) { throw new Error('Invalid feature-type. Only "accept" is supported'); } const disclosures = [ { - 'feature-type': DiscoveryProtocolFeatureType.Accept, + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept, accept: this._options.packageManager.getSupportedProfiles() } ]; diff --git a/src/iden3comm/types/protocol/discovery-protocol.ts b/src/iden3comm/types/protocol/discovery-protocol.ts index 91e89b5d..e9e61650 100644 --- a/src/iden3comm/types/protocol/discovery-protocol.ts +++ b/src/iden3comm/types/protocol/discovery-protocol.ts @@ -1,6 +1,11 @@ import { PROTOCOL_MESSAGE_TYPE } from '../../constants'; import { BasicMessage } from '../packer'; +/** @beta DiscoverFeatureQueryType is enum for query type fields */ +export enum DiscoverFeatureQueryType { + FeatureType = 'feature-type' +} + /** @beta DiscoveryProtocolFeatureType is enum for supported feature-types */ export enum DiscoveryProtocolFeatureType { Accept = 'accept' @@ -15,7 +20,7 @@ export type DiscoverFeatureQueriesMessage = BasicMessage & { /** @beta DiscoverFeatureQueriesBody is struct the represents discover feature queries body */ export type DiscoverFeatureQueriesBody = { queries: { - 'feature-type': DiscoveryProtocolFeatureType | string; + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType; }[]; }; @@ -32,6 +37,6 @@ export type DiscoverFeatureDiscloseBody = { /** @beta DiscoverFeatureDisclosure is struct the represents discover feature disclosure */ export type DiscoverFeatureDisclosure = { - 'feature-type': DiscoveryProtocolFeatureType | string; + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType; accept: Array; }; diff --git a/tests/handlers/discover-protocol.test.ts b/tests/handlers/discover-protocol.test.ts index dcb4ec78..638067d1 100644 --- a/tests/handlers/discover-protocol.test.ts +++ b/tests/handlers/discover-protocol.test.ts @@ -1,6 +1,7 @@ import { expect } from 'chai'; import { DiscoverFeatureQueriesMessage, + DiscoverFeatureQueryType, IPackageManager, JWSPacker, KMS, @@ -41,7 +42,7 @@ describe('discovery-protocol', () => { body: { disclosures } } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); expect(disclosures.length).to.be.eq(1); - expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); expect(disclosures[0].accept.length).to.be.eq(1); expect(disclosures[0].accept[0]).to.be.eq('env=application/iden3comm-plain-json'); }); @@ -60,7 +61,7 @@ describe('discovery-protocol', () => { expect(disclosures.length).to.be.eq(1); expect(disclosures[0].accept.length).to.be.eq(2); - expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); expect(disclosures[0].accept).to.include( 'env=application/iden3comm-signed-json&alg=ES256K,ES256K-R' @@ -80,7 +81,7 @@ describe('discovery-protocol', () => { expect(disclosures.length).to.be.eq(1); expect(disclosures[0].accept.length).to.be.eq(2); - expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); expect(disclosures[0].accept).to.include( 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' @@ -100,7 +101,7 @@ describe('discovery-protocol', () => { expect(disclosures.length).to.be.eq(1); expect(disclosures[0].accept.length).to.be.eq(3); - expect(disclosures[0]['feature-type']).to.be.eq('accept'); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); expect(disclosures[0].accept).to.include( 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' From 5e167106a23117f3cb562c6690a9d7482080ab35 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Mon, 16 Dec 2024 17:44:49 +0200 Subject: [PATCH 09/12] udate response with id field and add `match` to query --- src/iden3comm/handlers/discovery-protocol.ts | 96 +++++--- .../types/protocol/discovery-protocol.ts | 17 +- tests/handlers/discover-protocol.test.ts | 205 +++++++++++++++--- 3 files changed, 255 insertions(+), 63 deletions(-) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index 06aca696..86d97004 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -1,12 +1,13 @@ import { PROTOCOL_MESSAGE_TYPE } from '../constants'; -import { BasicMessage, IPackageManager } from '../types'; +import { BasicMessage, IPackageManager, ProtocolMessage } from '../types'; import * as uuid from 'uuid'; import { DiscoverFeatureDiscloseMessage, DiscoverFeatureDisclosure, DiscoverFeatureQueriesMessage, + DiscoverFeatureQuery, DiscoverFeatureQueryType, DiscoveryProtocolFeatureType } from '../types/protocol/discovery-protocol'; @@ -17,6 +18,7 @@ import { } from './message-handler'; import { getUnixTimestamp } from '@iden3/js-iden3-core'; import { verifyExpiresTime } from './common'; +import def from 'ajv/dist/vocabularies/discriminator'; /** * @beta @@ -26,6 +28,7 @@ import { verifyExpiresTime } from './common'; */ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; + supportedProtocols?: Array; } /** @@ -46,27 +49,21 @@ export type DiscoveryProtocolHandlerOptions = BasicHandlerOptions & { * @param opts - discovery-feature query options * @returns `DiscoverFeatureQueriesMessage` */ -export function createDiscoveryFeatureQueryMessage(opts?: { - featureTypes?: DiscoveryProtocolFeatureType[]; - from?: string; - to?: string; - expires_time?: number; -}): DiscoverFeatureQueriesMessage { +export function createDiscoveryFeatureQueryMessage( + queries: DiscoverFeatureQuery[], + opts?: { + from?: string; + to?: string; + expires_time?: number; + } +): DiscoverFeatureQueriesMessage { const uuidv4 = uuid.v4(); return { id: uuidv4, thid: uuidv4, type: PROTOCOL_MESSAGE_TYPE.DISCOVERY_PROTOCOL_QUERIES_MESSAGE_TYPE, body: { - queries: opts?.featureTypes?.length - ? opts.featureTypes.map((featureType) => ({ - [DiscoverFeatureQueryType.FeatureType]: featureType - })) - : [ - { - [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept - } - ] + queries }, from: opts?.from, to: opts?.to, @@ -173,24 +170,11 @@ export class DiscoveryProtocolHandler verifyExpiresTime(message); } - if (message.body.queries.length !== 1) { - throw new Error('Invalid number of queries. Only one query is supported'); + const disclosures: DiscoverFeatureDisclosure[] = []; + for (const query of message.body.queries) { + disclosures.push(...this.handleQuery(query)); } - if ( - message.body.queries[0][DiscoverFeatureQueryType.FeatureType] !== - DiscoveryProtocolFeatureType.Accept - ) { - throw new Error('Invalid feature-type. Only "accept" is supported'); - } - - const disclosures = [ - { - [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept, - accept: this._options.packageManager.getSupportedProfiles() - } - ]; - return Promise.resolve( createDiscoveryFeatureDiscloseMessage(disclosures, { to: message.from, @@ -201,4 +185,52 @@ export class DiscoveryProtocolHandler }) ); } + + private handleQuery(query: DiscoverFeatureQuery): DiscoverFeatureDisclosure[] { + let result: DiscoverFeatureDisclosure[] = []; + switch (query[DiscoverFeatureQueryType.FeatureType]) { + case DiscoveryProtocolFeatureType.Accept: + result = this.handleAcceptQuery(); + break; + case DiscoveryProtocolFeatureType.Protocol: + result = this.handleProtocolQuery(); + break; + } + + return this.handleMatch(result, query.match); + } + + private handleAcceptQuery(): DiscoverFeatureDisclosure[] { + const acceptProfiles = this._options.packageManager.getSupportedProfiles(); + return acceptProfiles.map((profile) => ({ + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept, + id: profile + })); + } + + private handleProtocolQuery(): DiscoverFeatureDisclosure[] { + return ( + this._options.supportedProtocols?.map((protocol) => ({ + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Protocol, + id: protocol + })) ?? [] + ); + } + + private handleMatch( + disclosures: DiscoverFeatureDisclosure[], + match?: string + ): DiscoverFeatureDisclosure[] { + if (!match || match === '*') { + return disclosures; + } + const regExp = this.wildcardToRegExp(match); + return disclosures.filter((disclosure) => regExp.test(disclosure.id)); + } + + private wildcardToRegExp(match: string): RegExp { + // Escape special regex characters, then replace `*` with `.*` + const regexPattern = match.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*'); + return new RegExp(`^${regexPattern}$`); + } } diff --git a/src/iden3comm/types/protocol/discovery-protocol.ts b/src/iden3comm/types/protocol/discovery-protocol.ts index e9e61650..911fad15 100644 --- a/src/iden3comm/types/protocol/discovery-protocol.ts +++ b/src/iden3comm/types/protocol/discovery-protocol.ts @@ -8,7 +8,10 @@ export enum DiscoverFeatureQueryType { /** @beta DiscoveryProtocolFeatureType is enum for supported feature-types */ export enum DiscoveryProtocolFeatureType { - Accept = 'accept' + Accept = 'accept', + Protocol = 'protocol', + GoalCode = 'goal-code', + Header = 'header' } /** @beta DiscoverFeatureQueriesMessage is struct the represents discover feature queries message */ @@ -19,9 +22,13 @@ export type DiscoverFeatureQueriesMessage = BasicMessage & { /** @beta DiscoverFeatureQueriesBody is struct the represents discover feature queries body */ export type DiscoverFeatureQueriesBody = { - queries: { - [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType; - }[]; + queries: DiscoverFeatureQuery[]; +}; + +/** @beta DiscoverFeatureQuery is struct the represents discover feature query */ +export type DiscoverFeatureQuery = { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType; + match?: string; }; /** @beta DiscoverFeatureDiscloseMessage is struct the represents discover feature disclose message */ @@ -38,5 +45,5 @@ export type DiscoverFeatureDiscloseBody = { /** @beta DiscoverFeatureDisclosure is struct the represents discover feature disclosure */ export type DiscoverFeatureDisclosure = { [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType; - accept: Array; + id: string; }; diff --git a/tests/handlers/discover-protocol.test.ts b/tests/handlers/discover-protocol.test.ts index 638067d1..c64c279f 100644 --- a/tests/handlers/discover-protocol.test.ts +++ b/tests/handlers/discover-protocol.test.ts @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { DiscoverFeatureQueriesMessage, DiscoverFeatureQueryType, + DiscoveryProtocolFeatureType, IPackageManager, JWSPacker, KMS, @@ -14,9 +15,10 @@ import { createDiscoveryFeatureQueryMessage } from '../../src/iden3comm/handlers/discovery-protocol'; import { DIDResolutionResult } from 'did-resolver'; +import { PROTOCOL_MESSAGE_TYPE } from '../../src/iden3comm/constants'; describe('discovery-protocol', () => { - let discoveryFeatureQueryMessage: DiscoverFeatureQueriesMessage; + let acceptQueryMessage: DiscoverFeatureQueriesMessage; let jwsPacker: JWSPacker; let zkpPacker: ZKPPacker; let plainPacker: PlainPacker; @@ -28,7 +30,9 @@ describe('discovery-protocol', () => { zkpPacker = new ZKPPacker(new Map(), new Map()); plainPacker = new PlainPacker(); - discoveryFeatureQueryMessage = createDiscoveryFeatureQueryMessage(); + acceptQueryMessage = createDiscoveryFeatureQueryMessage([ + { [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept } + ]); }); it('plain message accept disclosures', async () => { @@ -40,11 +44,12 @@ describe('discovery-protocol', () => { const { body: { disclosures } - } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); + } = await discoveryProtocolHandler.handleDiscoveryQuery(acceptQueryMessage); expect(disclosures.length).to.be.eq(1); - expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); - expect(disclosures[0].accept.length).to.be.eq(1); - expect(disclosures[0].accept[0]).to.be.eq('env=application/iden3comm-plain-json'); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[0].id).to.be.eq('env=application/iden3comm-plain-json'); }); it('jws and plain message accept disclosures', async () => { @@ -57,15 +62,18 @@ describe('discovery-protocol', () => { const { body: { disclosures } - } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); - expect(disclosures.length).to.be.eq(1); + } = await discoveryProtocolHandler.handleDiscoveryQuery(acceptQueryMessage); + expect(disclosures.length).to.be.eq(2); - expect(disclosures[0].accept.length).to.be.eq(2); - expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); - expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); - expect(disclosures[0].accept).to.include( - 'env=application/iden3comm-signed-json&alg=ES256K,ES256K-R' + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[1][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept ); + const disclosureIds = disclosures.map((d) => d.id); + expect(disclosureIds).to.include('env=application/iden3comm-plain-json'); + expect(disclosureIds).to.include('env=application/iden3comm-signed-json&alg=ES256K,ES256K-R'); }); it('zkp and plain message accept disclosures', async () => { @@ -77,13 +85,18 @@ describe('discovery-protocol', () => { const { body: { disclosures } - } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); - expect(disclosures.length).to.be.eq(1); + } = await discoveryProtocolHandler.handleDiscoveryQuery(acceptQueryMessage); + expect(disclosures.length).to.be.eq(2); - expect(disclosures[0].accept.length).to.be.eq(2); - expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); - expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); - expect(disclosures[0].accept).to.include( + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[1][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + const disclosureIds = disclosures.map((d) => d.id); + expect(disclosureIds).to.include('env=application/iden3comm-plain-json'); + expect(disclosureIds).to.include( 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' ); }); @@ -97,17 +110,157 @@ describe('discovery-protocol', () => { const { body: { disclosures } - } = await discoveryProtocolHandler.handleDiscoveryQuery(discoveryFeatureQueryMessage); + } = await discoveryProtocolHandler.handleDiscoveryQuery(acceptQueryMessage); + expect(disclosures.length).to.be.eq(3); + + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[1][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[2][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + const disclosureIds = disclosures.map((d) => d.id); + expect(disclosureIds).to.include('env=application/iden3comm-plain-json'); + expect(disclosureIds).to.include( + 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' + ); + expect(disclosureIds).to.include('env=application/iden3comm-signed-json&alg=ES256K,ES256K-R'); + }); + + it('zkp, jws and plain message accept disclosures with exact match', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([new PlainPacker(), plainPacker, zkpPacker, jwsPacker]); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const acceptQueryMessageWithMatch = createDiscoveryFeatureQueryMessage([ + { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept, + match: 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' + } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(acceptQueryMessageWithMatch); expect(disclosures.length).to.be.eq(1); - expect(disclosures[0].accept.length).to.be.eq(3); - expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq('accept'); - expect(disclosures[0].accept).to.include('env=application/iden3comm-plain-json'); - expect(disclosures[0].accept).to.include( + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[0].id).to.include( 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2' ); - expect(disclosures[0].accept).to.include( - 'env=application/iden3comm-signed-json&alg=ES256K,ES256K-R' + }); + + it('feature-type: protocol with protocol version match', async () => { + const packageManager: IPackageManager = new PackageManager(); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager, + supportedProtocols: [ + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE + ] + }); + + const protocolQueryMessage = createDiscoveryFeatureQueryMessage([ + { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Protocol, + match: 'https://iden3-communication.io/authorization/1.*' + } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(protocolQueryMessage); + expect(disclosures.length).to.be.eq(2); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Protocol + ); + expect(disclosures[1][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Protocol ); + const disclosureIds = disclosures.map((d) => d.id); + expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); + expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); + }); + + it('feature-type: protocol with protocol version mismatch', async () => { + const packageManager: IPackageManager = new PackageManager(); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager, + supportedProtocols: [ + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE + ] + }); + + const protocolQueryMessage = createDiscoveryFeatureQueryMessage([ + { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Protocol, + match: 'https://iden3-communication.io/authorization/44.*' + } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(protocolQueryMessage); + expect(disclosures.length).to.be.eq(0); + }); + + it('feature-type: protocol and accept', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([plainPacker]); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager, + supportedProtocols: [ + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE + ] + }); + + const protocolQueryMessage = createDiscoveryFeatureQueryMessage([ + { [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept }, + { [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Protocol } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(protocolQueryMessage); + expect(disclosures.length).to.be.eq(3); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Accept + ); + expect(disclosures[1][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Protocol + ); + expect(disclosures[2][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Protocol + ); + const disclosureIds = disclosures.map((d) => d.id); + expect(disclosureIds).to.include('env=application/iden3comm-plain-json'); + expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); + expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); + }); + + it('feature-type: header', async () => { + const packageManager: IPackageManager = new PackageManager(); + packageManager.registerPackers([plainPacker]); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const protocolQueryMessage = createDiscoveryFeatureQueryMessage([ + { [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Header } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(protocolQueryMessage); + expect(disclosures.length).to.be.eq(0); }); }); From 5266277b59f03519168b26a0b1fd41d8ef88c391 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Mon, 16 Dec 2024 18:27:13 +0200 Subject: [PATCH 10/12] add GoalCode --- src/iden3comm/handlers/discovery-protocol.ts | 18 ++++++-- tests/handlers/discover-protocol.test.ts | 47 ++++++++++++++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index 86d97004..17aa6d12 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -18,7 +18,6 @@ import { } from './message-handler'; import { getUnixTimestamp } from '@iden3/js-iden3-core'; import { verifyExpiresTime } from './common'; -import def from 'ajv/dist/vocabularies/discriminator'; /** * @beta @@ -28,7 +27,8 @@ import def from 'ajv/dist/vocabularies/discriminator'; */ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; - supportedProtocols?: Array; + protocols?: Array; + goalCodes?: Array; } /** @@ -195,6 +195,9 @@ export class DiscoveryProtocolHandler case DiscoveryProtocolFeatureType.Protocol: result = this.handleProtocolQuery(); break; + case DiscoveryProtocolFeatureType.GoalCode: + result = this.handleGoalCodeQuery(); + break; } return this.handleMatch(result, query.match); @@ -210,13 +213,22 @@ export class DiscoveryProtocolHandler private handleProtocolQuery(): DiscoverFeatureDisclosure[] { return ( - this._options.supportedProtocols?.map((protocol) => ({ + this._options.protocols?.map((protocol) => ({ [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Protocol, id: protocol })) ?? [] ); } + private handleGoalCodeQuery(): DiscoverFeatureDisclosure[] { + return ( + this._options.goalCodes?.map((goalCode) => ({ + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.GoalCode, + id: goalCode + })) ?? [] + ); + } + private handleMatch( disclosures: DiscoverFeatureDisclosure[], match?: string diff --git a/tests/handlers/discover-protocol.test.ts b/tests/handlers/discover-protocol.test.ts index c64c279f..5917481b 100644 --- a/tests/handlers/discover-protocol.test.ts +++ b/tests/handlers/discover-protocol.test.ts @@ -161,7 +161,7 @@ describe('discovery-protocol', () => { const packageManager: IPackageManager = new PackageManager(); const discoveryProtocolHandler = new DiscoveryProtocolHandler({ packageManager, - supportedProtocols: [ + protocols: [ PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE ] @@ -189,11 +189,52 @@ describe('discovery-protocol', () => { expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); }); + it('feature-type: protocol and goal-code with protocol version match', async () => { + const packageManager: IPackageManager = new PackageManager(); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager, + protocols: [ + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, + PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE + ], + goalCodes: ['unit.testing.some.goal-code'] + }); + + const protocolQueryMessage = createDiscoveryFeatureQueryMessage([ + { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Protocol, + match: 'https://iden3-communication.io/authorization/1.*' + }, + { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.GoalCode, + match: 'unit.testing.*' + } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(protocolQueryMessage); + expect(disclosures.length).to.be.eq(3); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Protocol + ); + expect(disclosures[1][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Protocol + ); + expect(disclosures[2][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.GoalCode + ); + const disclosureIds = disclosures.map((d) => d.id); + expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); + expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); + expect(disclosureIds).to.include('unit.testing.some.goal-code'); + }); + it('feature-type: protocol with protocol version mismatch', async () => { const packageManager: IPackageManager = new PackageManager(); const discoveryProtocolHandler = new DiscoveryProtocolHandler({ packageManager, - supportedProtocols: [ + protocols: [ PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE ] @@ -217,7 +258,7 @@ describe('discovery-protocol', () => { packageManager.registerPackers([plainPacker]); const discoveryProtocolHandler = new DiscoveryProtocolHandler({ packageManager, - supportedProtocols: [ + protocols: [ PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE ] From b662f471859e37c0c94ad6b4dec71e9573165b0e Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Mon, 16 Dec 2024 19:04:29 +0200 Subject: [PATCH 11/12] handleHeaderQuery --- src/iden3comm/handlers/discovery-protocol.ts | 27 ++++++++++++++++++++ tests/handlers/discover-protocol.test.ts | 23 +++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/iden3comm/handlers/discovery-protocol.ts b/src/iden3comm/handlers/discovery-protocol.ts index 17aa6d12..a3714e0b 100644 --- a/src/iden3comm/handlers/discovery-protocol.ts +++ b/src/iden3comm/handlers/discovery-protocol.ts @@ -29,6 +29,7 @@ export interface DiscoveryProtocolOptions { packageManager: IPackageManager; protocols?: Array; goalCodes?: Array; + headers?: Array; } /** @@ -142,6 +143,20 @@ export class DiscoveryProtocolHandler */ constructor(private readonly _options: DiscoveryProtocolOptions) { super(); + const headers = [ + 'id', + 'typ', + 'type', + 'thid', + 'body', + 'from', + 'to', + 'created_time', + 'expires_time' + ]; + if (!_options.headers) { + _options.headers = headers; + } } /** @@ -198,6 +213,9 @@ export class DiscoveryProtocolHandler case DiscoveryProtocolFeatureType.GoalCode: result = this.handleGoalCodeQuery(); break; + case DiscoveryProtocolFeatureType.Header: + result = this.handleHeaderQuery(); + break; } return this.handleMatch(result, query.match); @@ -229,6 +247,15 @@ export class DiscoveryProtocolHandler ); } + private handleHeaderQuery(): DiscoverFeatureDisclosure[] { + return ( + this._options.headers?.map((header) => ({ + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Header, + id: header + })) ?? [] + ); + } + private handleMatch( disclosures: DiscoverFeatureDisclosure[], match?: string diff --git a/tests/handlers/discover-protocol.test.ts b/tests/handlers/discover-protocol.test.ts index 5917481b..74c3a697 100644 --- a/tests/handlers/discover-protocol.test.ts +++ b/tests/handlers/discover-protocol.test.ts @@ -230,6 +230,29 @@ describe('discovery-protocol', () => { expect(disclosureIds).to.include('unit.testing.some.goal-code'); }); + it('feature-type: header', async () => { + const packageManager: IPackageManager = new PackageManager(); + const discoveryProtocolHandler = new DiscoveryProtocolHandler({ + packageManager + }); + + const protocolQueryMessage = createDiscoveryFeatureQueryMessage([ + { + [DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Header, + match: 'expires_time' + } + ]); + + const { + body: { disclosures } + } = await discoveryProtocolHandler.handleDiscoveryQuery(protocolQueryMessage); + expect(disclosures.length).to.be.eq(1); + expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq( + DiscoveryProtocolFeatureType.Header + ); + expect(disclosures[0].id).to.be.eq('expires_time'); + }); + it('feature-type: protocol with protocol version mismatch', async () => { const packageManager: IPackageManager = new PackageManager(); const discoveryProtocolHandler = new DiscoveryProtocolHandler({ From 04cc2029e40ee06024f1f35751d4c3b9d1bdbd1a Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Mon, 16 Dec 2024 19:16:38 +0200 Subject: [PATCH 12/12] fix unit --- tests/handlers/discover-protocol.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/handlers/discover-protocol.test.ts b/tests/handlers/discover-protocol.test.ts index 74c3a697..e5c117f0 100644 --- a/tests/handlers/discover-protocol.test.ts +++ b/tests/handlers/discover-protocol.test.ts @@ -311,11 +311,12 @@ describe('discovery-protocol', () => { expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE); }); - it('feature-type: header', async () => { + it('feature-type: empty headers', async () => { const packageManager: IPackageManager = new PackageManager(); packageManager.registerPackers([plainPacker]); const discoveryProtocolHandler = new DiscoveryProtocolHandler({ - packageManager + packageManager, + headers: [] }); const protocolQueryMessage = createDiscoveryFeatureQueryMessage([