@sphereon/ssi-sdk.presentation-exchange 0.11.1-next.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.yalc/@veramo/kv-store/LICENSE +201 -0
  2. package/.yalc/@veramo/kv-store/README.md +132 -0
  3. package/.yalc/@veramo/kv-store/build/index.d.ts +11 -0
  4. package/.yalc/@veramo/kv-store/build/index.js +45 -0
  5. package/.yalc/@veramo/kv-store/build/key-value-store.d.ts +27 -0
  6. package/.yalc/@veramo/kv-store/build/key-value-store.js +143 -0
  7. package/.yalc/@veramo/kv-store/build/key-value-types.d.ts +51 -0
  8. package/.yalc/@veramo/kv-store/build/key-value-types.js +3 -0
  9. package/.yalc/@veramo/kv-store/build/keyv/keyv-types.d.ts +62 -0
  10. package/.yalc/@veramo/kv-store/build/keyv/keyv-types.js +3 -0
  11. package/.yalc/@veramo/kv-store/build/keyv/keyv.d.ts +53 -0
  12. package/.yalc/@veramo/kv-store/build/keyv/keyv.js +385 -0
  13. package/.yalc/@veramo/kv-store/build/store-adapters/index.d.ts +3 -0
  14. package/.yalc/@veramo/kv-store/build/store-adapters/index.js +30 -0
  15. package/.yalc/@veramo/kv-store/build/store-adapters/tiered/index.d.ts +32 -0
  16. package/.yalc/@veramo/kv-store/build/store-adapters/tiered/index.js +301 -0
  17. package/.yalc/@veramo/kv-store/build/store-adapters/tiered/types.d.ts +14 -0
  18. package/.yalc/@veramo/kv-store/build/store-adapters/tiered/types.js +3 -0
  19. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/entities/keyValueStoreEntity.d.ts +11 -0
  20. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/entities/keyValueStoreEntity.js +50 -0
  21. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/index.d.ts +41 -0
  22. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/index.js +186 -0
  23. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/migrations/1.createKVDatabase.d.ts +14 -0
  24. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/migrations/1.createKVDatabase.js +90 -0
  25. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/migrations/index.d.ts +10 -0
  26. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/migrations/index.js +13 -0
  27. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/types.d.ts +15 -0
  28. package/.yalc/@veramo/kv-store/build/store-adapters/typeorm/types.js +3 -0
  29. package/.yalc/@veramo/kv-store/build/tsdoc-metadata.json +11 -0
  30. package/.yalc/@veramo/kv-store/package.json +39 -0
  31. package/.yalc/@veramo/kv-store/src/__tests__/keyv.test.ts +204 -0
  32. package/.yalc/@veramo/kv-store/src/__tests__/kvstore.test.ts +93 -0
  33. package/.yalc/@veramo/kv-store/src/index.ts +10 -0
  34. package/.yalc/@veramo/kv-store/src/key-value-store.ts +109 -0
  35. package/.yalc/@veramo/kv-store/src/key-value-types.ts +97 -0
  36. package/.yalc/@veramo/kv-store/src/keyv/keyv-types.ts +71 -0
  37. package/.yalc/@veramo/kv-store/src/keyv/keyv.ts +282 -0
  38. package/.yalc/@veramo/kv-store/src/store-adapters/index.ts +2 -0
  39. package/.yalc/@veramo/kv-store/src/store-adapters/tiered/index.ts +158 -0
  40. package/.yalc/@veramo/kv-store/src/store-adapters/tiered/types.ts +16 -0
  41. package/.yalc/@veramo/kv-store/src/store-adapters/typeorm/entities/keyValueStoreEntity.ts +20 -0
  42. package/.yalc/@veramo/kv-store/src/store-adapters/typeorm/index.ts +122 -0
  43. package/.yalc/@veramo/kv-store/src/store-adapters/typeorm/migrations/1.createKVDatabase.ts +47 -0
  44. package/.yalc/@veramo/kv-store/src/store-adapters/typeorm/migrations/index.ts +10 -0
  45. package/.yalc/@veramo/kv-store/src/store-adapters/typeorm/types.ts +18 -0
  46. package/.yalc/@veramo/kv-store/yalc.sig +1 -0
  47. package/LICENSE +201 -0
  48. package/README.md +56 -0
  49. package/dist/agent/PresentationExchange.d.ts +25 -0
  50. package/dist/agent/PresentationExchange.d.ts.map +1 -0
  51. package/dist/agent/PresentationExchange.js +182 -0
  52. package/dist/agent/PresentationExchange.js.map +1 -0
  53. package/dist/functions.d.ts +12 -0
  54. package/dist/functions.d.ts.map +1 -0
  55. package/dist/functions.js +41 -0
  56. package/dist/functions.js.map +1 -0
  57. package/dist/index.d.ts +9 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +27 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/types/IPresentationExchange.d.ts +81 -0
  62. package/dist/types/IPresentationExchange.d.ts.map +1 -0
  63. package/dist/types/IPresentationExchange.js +3 -0
  64. package/dist/types/IPresentationExchange.js.map +1 -0
  65. package/package.json +67 -0
  66. package/plugin.schema.json +329 -0
  67. package/src/agent/PresentationExchange.ts +204 -0
  68. package/src/functions.ts +56 -0
  69. package/src/index.ts +8 -0
  70. package/src/types/IPresentationExchange.ts +114 -0
@@ -0,0 +1,204 @@
1
+ import {
2
+ IDefinitionCredentialFilterArgs,
3
+ IDefinitionExistsArgs,
4
+ IDefinitionGetArgs,
5
+ IDefinitionPersistArgs,
6
+ IDefinitionRemoveArgs,
7
+ IDefinitionsClearArgs,
8
+ IPEXFilterResult,
9
+ IPEXFilterResultWithInputDescriptor,
10
+ IRequiredContext,
11
+ PEXOpts,
12
+ schema,
13
+ VersionDiscoveryResult,
14
+ } from '../index'
15
+ import { FindCredentialsArgs, IAgentPlugin } from '@veramo/core'
16
+
17
+ import { IPresentationExchange } from '../types/IPresentationExchange'
18
+ import { IKeyValueStore, IValueData, KeyValueStore } from '@veramo/kv-store'
19
+ import { Checked, IPresentationDefinition, PEX } from '@sphereon/pex'
20
+ import { CredentialMapper, JWT_PROOF_TYPE_2020, W3CVerifiableCredential } from '@sphereon/ssi-types'
21
+ import { InputDescriptorV1, InputDescriptorV2 } from '@sphereon/pex-models'
22
+ import { toDIDs } from '@sphereon/ssi-sdk-ext.did-utils'
23
+
24
+ export class PresentationExchange implements IAgentPlugin {
25
+ private readonly _stores: Map<string, IKeyValueStore<IPresentationDefinition>>
26
+ readonly schema = schema.IDidAuthSiopOpAuthenticator
27
+ private readonly defaultStore: string
28
+ private readonly defaultNamespace: string
29
+
30
+ readonly methods: IPresentationExchange = {
31
+ pexStoreGetDefinition: this.pexStoreGetDefinition.bind(this),
32
+ pexStorePersistDefinition: this.pexStorePersistDefinition.bind(this),
33
+ pexStoreHasDefinition: this.pexStoreHasDefinition.bind(this),
34
+ pexStoreRemoveDefinition: this.pexStoreRemoveDefinition.bind(this),
35
+ pexStoreClearDefinitions: this.pexStoreClearDefinitions.bind(this),
36
+ pexDefinitionVersion: this.pexDefinitionVersion.bind(this),
37
+ pexDefinitionFilterCredentials: this.pexDefinitionFilterCredentials.bind(this),
38
+ pexDefinitionFilterCredentialsPerInputDescriptor: this.pexDefinitionFilterCredentialsPerInputDescriptor.bind(this),
39
+ }
40
+
41
+ constructor(opts?: PEXOpts) {
42
+ this.defaultStore = opts?.defaultStore ?? '_default'
43
+ this.defaultNamespace = opts?.defaultNamespace ?? 'pex'
44
+ if (opts?.stores && opts.stores instanceof Map) {
45
+ this._stores = opts.stores
46
+ } else if (opts?.stores) {
47
+ this._stores = new Map().set(this.defaultStore, opts.stores)
48
+ } else {
49
+ this._stores = new Map().set(
50
+ this.defaultStore,
51
+ new KeyValueStore({
52
+ namespace: this.defaultNamespace,
53
+ store: new Map<string, IPresentationDefinition>(),
54
+ })
55
+ )
56
+ }
57
+ if (opts && Array.isArray(opts?.importDefinitions)) {
58
+ opts.importDefinitions.forEach(this.pexStorePersistDefinition)
59
+ }
60
+ }
61
+
62
+ private async pexStoreGetDefinition({ definitionId, storeId, namespace }: IDefinitionGetArgs): Promise<IPresentationDefinition | undefined> {
63
+ return this.store({ storeId }).get(this.prefix({ namespace, definitionId }))
64
+ }
65
+
66
+ private async pexStoreHasDefinition({ definitionId, storeId, namespace }: IDefinitionExistsArgs): Promise<boolean> {
67
+ return this.store({ storeId }).has(this.prefix({ namespace, definitionId }))
68
+ }
69
+
70
+ private async pexStorePersistDefinition(args: IDefinitionPersistArgs): Promise<IValueData<IPresentationDefinition>> {
71
+ const { definition, ttl, storeId, namespace } = args
72
+ if (args?.validation !== false) {
73
+ let invalids: Checked[] = []
74
+
75
+ try {
76
+ const result = PEX.validateDefinition(definition) // throws an error in case the def is not valid
77
+ const validations = Array.isArray(result) ? result : [result]
78
+ invalids = validations.filter((v) => v.status === 'error')
79
+ } catch (error) {
80
+ invalids.push({
81
+ status: 'error',
82
+ message:
83
+ typeof error === 'string'
84
+ ? error
85
+ : typeof error === 'object' && 'message' in (error as object)
86
+ ? (error as Error).message
87
+ : 'unknown error',
88
+ tag: 'validation',
89
+ })
90
+ }
91
+ if (invalids.length > 0) {
92
+ throw Error(`Invalid definition. ${invalids.map((v) => v.message).toString()}`)
93
+ }
94
+ }
95
+ const definitionId = args.definitionId ?? definition.id
96
+ const existing = await this.store({ storeId }).getAsValueData(this.prefix({ namespace, definitionId }))
97
+ if (!existing.value || (existing.value && args.overwriteExisting !== false)) {
98
+ return await this.store({ storeId }).set(this.prefix({ namespace, definitionId }), definition, ttl)
99
+ }
100
+ return existing
101
+ }
102
+
103
+ private async pexStoreRemoveDefinition({ storeId, definitionId, namespace }: IDefinitionRemoveArgs): Promise<boolean> {
104
+ return this.store({ storeId }).delete(this.prefix({ namespace, definitionId }))
105
+ }
106
+
107
+ private async pexStoreClearDefinitions({ storeId }: IDefinitionsClearArgs): Promise<boolean> {
108
+ return await this.store({ storeId })
109
+ .clear()
110
+ .then(() => true)
111
+ }
112
+
113
+ async pexDefinitionVersion(presentationDefinition: IPresentationDefinition): Promise<VersionDiscoveryResult> {
114
+ return PEX.definitionVersionDiscovery(presentationDefinition)
115
+ }
116
+
117
+ async pexDefinitionFilterCredentials(args: IDefinitionCredentialFilterArgs, context: IRequiredContext): Promise<IPEXFilterResult> {
118
+ const credentials = await this.pexFilterCredentials(args.credentialFilterOpts ?? {}, context)
119
+ const holderDIDs = args.holderDIDs ? toDIDs(args.holderDIDs) : toDIDs(await context.agent.dataStoreORMGetIdentifiers())
120
+ const selectResults = new PEX().selectFrom(args.presentationDefinition, credentials ?? [], {
121
+ ...args,
122
+ holderDIDs,
123
+ limitDisclosureSignatureSuites: args.limitDisclosureSignatureSuites ?? ['BbsBlsSignature2020'],
124
+ })
125
+ return {
126
+ id: args.presentationDefinition.id,
127
+ selectResults,
128
+ filteredCredentials: selectResults.verifiableCredential?.map((vc) => CredentialMapper.storedCredentialToOriginalFormat(vc)) ?? [],
129
+ }
130
+ }
131
+
132
+ async pexDefinitionFilterCredentialsPerInputDescriptor(
133
+ args: IDefinitionCredentialFilterArgs,
134
+ context: IRequiredContext
135
+ ): Promise<IPEXFilterResultWithInputDescriptor[]> {
136
+ const origDefinition = args.presentationDefinition
137
+ const credentials = await this.pexFilterCredentials(args.credentialFilterOpts ?? {}, context)
138
+ const holderDIDs = args.holderDIDs ? toDIDs(args.holderDIDs) : toDIDs(await context.agent.dataStoreORMGetIdentifiers())
139
+ const limitDisclosureSignatureSuites = args.limitDisclosureSignatureSuites
140
+
141
+ const promises = new Map<InputDescriptorV1 | InputDescriptorV2, Promise<IPEXFilterResult>>()
142
+ origDefinition.input_descriptors.forEach((inputDescriptor) => {
143
+ const presentationDefinition = {
144
+ id: inputDescriptor.id,
145
+ input_descriptors: [inputDescriptor],
146
+ }
147
+ promises.set(
148
+ inputDescriptor,
149
+ this.pexDefinitionFilterCredentials(
150
+ {
151
+ credentialFilterOpts: { verifiableCredentials: credentials },
152
+ presentationDefinition,
153
+ holderDIDs,
154
+ limitDisclosureSignatureSuites,
155
+ },
156
+ context
157
+ )
158
+ )
159
+ })
160
+ await Promise.all(promises.values())
161
+ const result: IPEXFilterResultWithInputDescriptor[] = []
162
+ for (const entry of promises.entries()) {
163
+ result.push({ ...(await entry[1]), inputDescriptor: entry[0] })
164
+ }
165
+ return result
166
+ }
167
+
168
+ private async pexFilterCredentials(
169
+ filterOpts: {
170
+ verifiableCredentials?: W3CVerifiableCredential[]
171
+ filter?: FindCredentialsArgs
172
+ },
173
+ context: IRequiredContext
174
+ ): Promise<W3CVerifiableCredential[]> {
175
+ if (filterOpts?.verifiableCredentials && filterOpts.verifiableCredentials.length > 0) {
176
+ return filterOpts.verifiableCredentials as W3CVerifiableCredential[]
177
+ }
178
+ return (await context.agent.dataStoreORMGetVerifiableCredentials(filterOpts?.filter))
179
+ .map((uniqueVC) => uniqueVC.verifiableCredential)
180
+ .map((vc) => (vc.proof && vc.proof.type === JWT_PROOF_TYPE_2020 ? vc.proof.jwt : vc))
181
+ }
182
+
183
+ /*private assertIdentifier(identifier?: IIdentifier): void {
184
+ if (!identifier) {
185
+ throw Error(`OID4VP needs an identifier at this point`)
186
+ }
187
+ }*/
188
+
189
+ private store({ storeId }: { storeId?: string }): IKeyValueStore<IPresentationDefinition> {
190
+ const store = this._stores.get(storeId ?? this.defaultStore)
191
+ if (!store) {
192
+ throw Error(`Could not get definition store: ${storeId ?? this.defaultStore}`)
193
+ }
194
+ return store
195
+ }
196
+
197
+ private namespace({ namespace }: { namespace?: string }): string {
198
+ return namespace ?? this.defaultStore
199
+ }
200
+
201
+ private prefix({ namespace, definitionId }: { namespace?: string; definitionId: string }) {
202
+ return `${this.namespace({ namespace })}:${definitionId}`
203
+ }
204
+ }
@@ -0,0 +1,56 @@
1
+ import { IPEXOptions, IPEXPresentationSignCallback, IRequiredContext } from './types/IPresentationExchange'
2
+ import { IPresentationDefinition } from '@sphereon/pex'
3
+ import { PresentationPayload } from '@veramo/core'
4
+ import { CredentialMapper, W3CVerifiablePresentation } from '@sphereon/ssi-types'
5
+ import { Format } from '@sphereon/pex-models'
6
+
7
+ export async function getPresentationDefinition(pexOptions?: IPEXOptions): Promise<IPresentationDefinition | undefined> {
8
+ return pexOptions?.definition
9
+ /*const store = await getPresentationDefinitionStore(pexOptions)
10
+ return store && pexOptions?.definitionId ? store.get(pexOptions?.definitionId) : undefined*/
11
+ }
12
+
13
+ export async function createPEXPresentationSignCallback(
14
+ {
15
+ kid,
16
+ fetchRemoteContexts,
17
+ format,
18
+ domain,
19
+ challenge,
20
+ }: {
21
+ kid: string
22
+ fetchRemoteContexts?: boolean
23
+ format?: Format
24
+ domain?: string
25
+ challenge?: string
26
+ },
27
+ context: IRequiredContext
28
+ ): Promise<IPEXPresentationSignCallback> {
29
+ return async ({
30
+ presentation,
31
+ domain,
32
+ presentationDefinition,
33
+ format,
34
+ challenge,
35
+ }: {
36
+ presentation: PresentationPayload
37
+ presentationDefinition: IPresentationDefinition
38
+ format?: Format
39
+ domain?: string
40
+ challenge?: string
41
+ }): Promise<W3CVerifiablePresentation> => {
42
+ const formatOptions = format ?? presentationDefinition.format
43
+ const proofFormat = formatOptions && (!!formatOptions.ldp || !!formatOptions.ldp_vp) ? 'lds' : 'jwt'
44
+
45
+ const vp = await context.agent.createVerifiablePresentation({
46
+ presentation,
47
+ keyRef: kid,
48
+ domain,
49
+ challenge,
50
+ fetchRemoteContexts: fetchRemoteContexts !== undefined ? fetchRemoteContexts : true,
51
+ proofFormat,
52
+ })
53
+ // makes sure we extract an actual JWT from the internal representation in case it is a JWT
54
+ return CredentialMapper.storedPresentationToOriginalFormat(vp as W3CVerifiablePresentation)
55
+ }
56
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @public
3
+ */
4
+ const schema = require('../plugin.schema.json')
5
+ export { schema }
6
+ export { PresentationExchange } from './agent/PresentationExchange'
7
+ export * from './types/IPresentationExchange'
8
+ export * from './functions'
@@ -0,0 +1,114 @@
1
+ import {
2
+ DIDDocumentSection,
3
+ FindCredentialsArgs,
4
+ IAgentContext,
5
+ IDataStoreORM,
6
+ IDIDManager,
7
+ IIdentifier,
8
+ IPluginMethodMap,
9
+ PresentationPayload,
10
+ } from '@veramo/core'
11
+ import { W3CVerifiableCredential, W3CVerifiablePresentation } from '@sphereon/ssi-types'
12
+ import { IKeyValueStore, IValueData } from '@veramo/kv-store'
13
+ import { IPresentationDefinition, PEVersion, SelectResults } from '@sphereon/pex'
14
+ import { Format, InputDescriptorV1, InputDescriptorV2 } from '@sphereon/pex-models'
15
+
16
+ export interface IPresentationExchange extends IPluginMethodMap {
17
+ pexStoreGetDefinition(args: IDefinitionGetArgs): Promise<IPresentationDefinition | undefined>
18
+
19
+ pexStoreHasDefinition(args: IDefinitionExistsArgs): Promise<boolean>
20
+
21
+ pexStorePersistDefinition(args: IDefinitionPersistArgs): Promise<IValueData<IPresentationDefinition>>
22
+
23
+ pexStoreRemoveDefinition(args: IDefinitionRemoveArgs): Promise<boolean>
24
+
25
+ pexStoreClearDefinitions(args: IDefinitionsClearArgs): Promise<boolean>
26
+
27
+ pexDefinitionVersion(presentationDefinition: IPresentationDefinition): Promise<VersionDiscoveryResult>
28
+
29
+ pexDefinitionFilterCredentials(args: IDefinitionCredentialFilterArgs, context: IRequiredContext): Promise<IPEXFilterResult>
30
+
31
+ pexDefinitionFilterCredentialsPerInputDescriptor(
32
+ args: IDefinitionCredentialFilterArgs,
33
+ context: IRequiredContext
34
+ ): Promise<IPEXFilterResultWithInputDescriptor[]>
35
+ }
36
+
37
+ export interface IDefinitionGetArgs {
38
+ definitionId: string
39
+ storeId?: string
40
+ namespace?: string
41
+ }
42
+
43
+ export type IDefinitionExistsArgs = IDefinitionGetArgs
44
+ export type IDefinitionClearArgs = IDefinitionGetArgs
45
+ export type IDefinitionRemoveArgs = IDefinitionGetArgs
46
+
47
+ export type IDefinitionImportArgs = IDefinitionPersistArgs
48
+
49
+ export interface IDefinitionPersistArgs {
50
+ definition: IPresentationDefinition // The actual Presentation definition to be stored/
51
+ definitionId?: string // Allows to define a custom key for storage. By default, the id of the definition will be used
52
+ overwriteExisting?: boolean // Whether to overwrite any existing definition by id. Defaults to true
53
+ validation?: boolean // Whether to check the definition. Defaults to true
54
+ ttl?: number // How long should the definition be stored in seconds. By default, it will be indefinite
55
+ storeId?: string // The store id to use. Allows you to use multiple different stores next to each-other
56
+ namespace?: string // The namespace (prefix) to use whilst storing the definition. Allows you to partition definitions
57
+ }
58
+
59
+ export interface IDefinitionsClearArgs {
60
+ storeId?: string
61
+ // namespace?: string
62
+ }
63
+
64
+ export interface IDefinitionCredentialFilterArgs {
65
+ presentationDefinition: IPresentationDefinition
66
+ credentialFilterOpts?: { verifiableCredentials?: W3CVerifiableCredential[]; filter?: FindCredentialsArgs }
67
+ holderDIDs?: (string | IIdentifier)[]
68
+ limitDisclosureSignatureSuites?: string[]
69
+ restrictToFormats?: Format
70
+ restrictToDIDMethods?: string[]
71
+ }
72
+
73
+ export interface PEXOpts {
74
+ defaultStore?: string
75
+ defaultNamespace?: string
76
+ stores?: Map<string, IKeyValueStore<IPresentationDefinition>> | IKeyValueStore<IPresentationDefinition>
77
+ importDefinitions?: IDefinitionImportArgs[]
78
+ }
79
+
80
+ export interface IPEXOptions {
81
+ // presentationVerifyCallback?: PresentationVerificationCallback
82
+ definition?: IPresentationDefinition
83
+ definitionId: string
84
+ }
85
+
86
+ export interface IPEXFilterResultWithInputDescriptor extends IPEXFilterResult {
87
+ inputDescriptor: InputDescriptorV1 | InputDescriptorV2
88
+ }
89
+
90
+ export interface IPEXFilterResult {
91
+ id: string
92
+ selectResults: SelectResults
93
+ filteredCredentials: W3CVerifiableCredential[]
94
+ }
95
+
96
+ export interface IIdentifierOpts {
97
+ identifier: IIdentifier | string
98
+ verificationMethodSection?: DIDDocumentSection
99
+ kid?: string
100
+ }
101
+
102
+ export interface VersionDiscoveryResult {
103
+ version?: PEVersion
104
+ error?: string
105
+ }
106
+
107
+ export type IPEXPresentationSignCallback = (args: IPEXPresentationSignCallBackParams) => Promise<W3CVerifiablePresentation>
108
+
109
+ export interface IPEXPresentationSignCallBackParams {
110
+ presentation: PresentationPayload
111
+ presentationDefinition: IPresentationDefinition
112
+ }
113
+
114
+ export type IRequiredContext = IAgentContext<IDataStoreORM & IDIDManager>