@twin.org/identity-service 0.9.1 → 0.9.2-next.10
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.
- package/dist/es/identityProfileRoutes.js +278 -1
- package/dist/es/identityProfileRoutes.js.map +1 -1
- package/dist/es/identityProfileService.js +25 -1
- package/dist/es/identityProfileService.js.map +1 -1
- package/dist/es/identityRoutes.js +2 -2
- package/dist/es/identityRoutes.js.map +1 -1
- package/dist/es/identityService.js +333 -171
- package/dist/es/identityService.js.map +1 -1
- package/dist/es/models/IIdentityServiceConstructorOptions.js.map +1 -1
- package/dist/types/identityProfileRoutes.d.ts +33 -1
- package/dist/types/identityProfileService.d.ts +29 -0
- package/dist/types/identityService.d.ts +29 -3
- package/dist/types/models/IIdentityServiceConstructorOptions.d.ts +9 -0
- package/docs/changelog.md +283 -0
- package/docs/open-api/spec.json +831 -132
- package/docs/reference/classes/IdentityProfileService.md +56 -0
- package/docs/reference/classes/IdentityService.md +90 -2
- package/docs/reference/functions/identitiesAdminList.md +31 -0
- package/docs/reference/functions/identityProfileAdminGet.md +31 -0
- package/docs/reference/functions/identityProfileAdminRemove.md +31 -0
- package/docs/reference/functions/identityProfileAdminUpdate.md +31 -0
- package/docs/reference/index.md +4 -0
- package/docs/reference/interfaces/IIdentityServiceConstructorOptions.md +22 -0
- package/locales/en.json +9 -1
- package/package.json +16 -14
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { HealthCategory, HealthStatus } from "@twin.org/api-models";
|
|
4
|
+
import { ContextIdKeys, ContextIdStore } from "@twin.org/context";
|
|
5
|
+
import { BaseError, ComponentFactory, GeneralError, Guards, Is, Urn } from "@twin.org/core";
|
|
6
|
+
import { AccountHelper } from "@twin.org/dlt-account";
|
|
7
|
+
import { DocumentHelper, IdentityConnectorFactory, IdentityMetricIds, IdentitySpanAttributes, IdentitySpanNames, IdentityMetrics, IdentityResolverConnectorFactory } from "@twin.org/identity-models";
|
|
5
8
|
import { DidVerificationMethodType, ProofTypes } from "@twin.org/standards-w3c-did";
|
|
6
9
|
import { MetricHelper } from "@twin.org/telemetry-models";
|
|
10
|
+
import { TracingHelper } from "@twin.org/tracing-models";
|
|
11
|
+
import { VaultConnectorFactory } from "@twin.org/vault-models";
|
|
7
12
|
import { Jwt } from "@twin.org/web";
|
|
8
13
|
/**
|
|
9
14
|
* Class which implements the identity contract.
|
|
@@ -18,11 +23,21 @@ export class IdentityService {
|
|
|
18
23
|
* @internal
|
|
19
24
|
*/
|
|
20
25
|
_defaultNamespace;
|
|
26
|
+
/**
|
|
27
|
+
* The vault connector type used for mnemonic migration during health check init.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
_vaultConnector;
|
|
21
31
|
/**
|
|
22
32
|
* The telemetry component.
|
|
23
33
|
* @internal
|
|
24
34
|
*/
|
|
25
35
|
_telemetryComponent;
|
|
36
|
+
/**
|
|
37
|
+
* The optional tracing component for recording spans.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
_tracingComponent;
|
|
26
41
|
/**
|
|
27
42
|
* Create a new instance of IdentityService.
|
|
28
43
|
* @param options The options for the service.
|
|
@@ -34,7 +49,9 @@ export class IdentityService {
|
|
|
34
49
|
throw new GeneralError(IdentityService.CLASS_NAME, "noConnectors");
|
|
35
50
|
}
|
|
36
51
|
this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
|
|
52
|
+
this._vaultConnector = VaultConnectorFactory.get(options?.vaultConnectorType ?? "vault");
|
|
37
53
|
this._telemetryComponent = ComponentFactory.getIfExists(options?.telemetryComponentType);
|
|
54
|
+
this._tracingComponent = ComponentFactory.getIfExists(options?.tracingComponentType);
|
|
38
55
|
}
|
|
39
56
|
/**
|
|
40
57
|
* Returns the class name of the component.
|
|
@@ -53,6 +70,109 @@ export class IdentityService {
|
|
|
53
70
|
}
|
|
54
71
|
await MetricHelper.createMetrics(this._telemetryComponent, IdentityMetrics);
|
|
55
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Creates a temporary DID document for the application health check.
|
|
75
|
+
* @param contextIds The context IDs accumulated by prior init steps.
|
|
76
|
+
*/
|
|
77
|
+
async healthApplicationInit(contextIds) {
|
|
78
|
+
// The wallet service has already setup a temporary controller DID mnemonic for the health check
|
|
79
|
+
// so we can use that to create a new document and add a verification method to it.
|
|
80
|
+
const controller = contextIds[ContextIdKeys.Organization];
|
|
81
|
+
if (!Is.stringValue(controller)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const connector = this.getConnectorByNamespace();
|
|
86
|
+
const doc = await connector.createDocument(controller);
|
|
87
|
+
await connector.addVerificationMethod(controller, doc.id, DidVerificationMethodType.AssertionMethod, "health-assertion");
|
|
88
|
+
// The original seed/mnemonic/keys were created with the temp orgId
|
|
89
|
+
// so we need to migrate them to the new document id so that the health check can resolve the DID.
|
|
90
|
+
await AccountHelper.renameAccountKeys(undefined, this._vaultConnector, controller, doc.id);
|
|
91
|
+
// Replace the updated contextIds with the new document id for the health check.
|
|
92
|
+
contextIds[ContextIdKeys.Organization] = doc.id;
|
|
93
|
+
}
|
|
94
|
+
catch { }
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Returns the application health status of the identity service by resolving the DID created
|
|
98
|
+
* in healthApplicationInit.
|
|
99
|
+
* @param callback Callback for deferred results.
|
|
100
|
+
* @returns The health status of the service.
|
|
101
|
+
*/
|
|
102
|
+
async healthApplication(callback) {
|
|
103
|
+
const contextIds = (await ContextIdStore.getContextIds()) ?? {};
|
|
104
|
+
const orgDid = contextIds[ContextIdKeys.Organization];
|
|
105
|
+
if (!Is.stringValue(orgDid)) {
|
|
106
|
+
return [
|
|
107
|
+
{
|
|
108
|
+
source: IdentityService.CLASS_NAME,
|
|
109
|
+
category: HealthCategory.Application,
|
|
110
|
+
status: HealthStatus.Error,
|
|
111
|
+
description: "healthDescription",
|
|
112
|
+
message: "createDocumentFailed",
|
|
113
|
+
data: {
|
|
114
|
+
did: orgDid
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const resolverConnector = IdentityResolverConnectorFactory.getIfExists(this._defaultNamespace);
|
|
121
|
+
if (!Is.undefined(resolverConnector)) {
|
|
122
|
+
const resolved = await resolverConnector.resolveDocument(orgDid);
|
|
123
|
+
return [
|
|
124
|
+
{
|
|
125
|
+
source: IdentityService.CLASS_NAME,
|
|
126
|
+
category: HealthCategory.Application,
|
|
127
|
+
status: Is.object(resolved) ? HealthStatus.Ok : HealthStatus.Error,
|
|
128
|
+
description: "healthDescription",
|
|
129
|
+
message: Is.object(resolved) ? undefined : "resolveDocumentFailed",
|
|
130
|
+
data: { did: orgDid }
|
|
131
|
+
}
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
return [
|
|
135
|
+
{
|
|
136
|
+
source: IdentityService.CLASS_NAME,
|
|
137
|
+
category: HealthCategory.Application,
|
|
138
|
+
status: HealthStatus.Ok,
|
|
139
|
+
description: "healthDescription",
|
|
140
|
+
data: { did: orgDid }
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
source: IdentityService.CLASS_NAME,
|
|
148
|
+
category: HealthCategory.Application,
|
|
149
|
+
status: HealthStatus.Error,
|
|
150
|
+
description: "healthDescription",
|
|
151
|
+
message: "resolveDocumentFailed",
|
|
152
|
+
data: { did: orgDid },
|
|
153
|
+
error: BaseError.fromError(error)
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Removes the DID document created in healthApplicationInit.
|
|
160
|
+
*/
|
|
161
|
+
async healthApplicationTeardown() {
|
|
162
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
163
|
+
const orgId = contextIds?.[ContextIdKeys.Organization];
|
|
164
|
+
if (!Is.stringValue(orgId)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const connector = this.getConnectorByNamespace();
|
|
169
|
+
await connector.removeVerificationMethod(orgId, `${orgId}#health-assertion`, {
|
|
170
|
+
removeKeys: true
|
|
171
|
+
});
|
|
172
|
+
await connector.removeDocument(orgId, orgId);
|
|
173
|
+
}
|
|
174
|
+
catch { }
|
|
175
|
+
}
|
|
56
176
|
/**
|
|
57
177
|
* Create a new identity.
|
|
58
178
|
* @param namespace The namespace of the connector to use for the identity, defaults to service configured namespace.
|
|
@@ -61,36 +181,42 @@ export class IdentityService {
|
|
|
61
181
|
*/
|
|
62
182
|
async identityCreate(namespace, controller) {
|
|
63
183
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
184
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.Create, undefined, async () => {
|
|
185
|
+
try {
|
|
186
|
+
const identityConnector = this.getConnectorByNamespace(namespace);
|
|
187
|
+
const result = await identityConnector.createDocument(controller);
|
|
188
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.DidsCreated, {
|
|
189
|
+
namespace: namespace ?? this._defaultNamespace
|
|
190
|
+
});
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "identityCreateFailed", undefined, error);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
75
197
|
}
|
|
76
198
|
/**
|
|
77
199
|
* Remove an identity.
|
|
78
200
|
* @param identity The id of the document to remove.
|
|
201
|
+
* @param options Optional settings.
|
|
202
|
+
* @param options.removeKeys Also remove any associated private keys from the vault.
|
|
79
203
|
* @param controller The controller of the identity who can make changes.
|
|
80
204
|
* @returns A promise that resolves when the identity has been removed.
|
|
81
205
|
*/
|
|
82
|
-
async identityRemove(identity, controller) {
|
|
206
|
+
async identityRemove(identity, options, controller) {
|
|
83
207
|
Guards.stringValue(IdentityService.CLASS_NAME, "identity", identity);
|
|
84
208
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
209
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.Remove, { attributes: { [IdentitySpanAttributes.Id]: identity } }, async () => {
|
|
210
|
+
try {
|
|
211
|
+
const identityConnector = this.getConnectorByUri(identity);
|
|
212
|
+
const result = await identityConnector.removeDocument(controller, identity, options);
|
|
213
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.DidsRemoved);
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "identityRemoveFailed", { identity }, error);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
94
220
|
}
|
|
95
221
|
/**
|
|
96
222
|
* Add a verification method to the document in JSON Web key Format.
|
|
@@ -106,34 +232,40 @@ export class IdentityService {
|
|
|
106
232
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
107
233
|
Urn.guard(IdentityService.CLASS_NAME, "identity", identity);
|
|
108
234
|
Guards.arrayOneOf(IdentityService.CLASS_NAME, "verificationMethodType", verificationMethodType, Object.values(DidVerificationMethodType));
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
235
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerificationMethodCreate, { attributes: { [IdentitySpanAttributes.Id]: identity } }, async () => {
|
|
236
|
+
try {
|
|
237
|
+
const identityConnector = this.getConnectorByUri(identity);
|
|
238
|
+
const verificationMethod = await identityConnector.addVerificationMethod(controller, identity, verificationMethodType, verificationMethodId);
|
|
239
|
+
return verificationMethod;
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verificationMethodCreateFailed", { identity }, error);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
117
245
|
}
|
|
118
246
|
/**
|
|
119
247
|
* Remove a verification method from the document.
|
|
120
248
|
* @param verificationMethodId The id of the verification method.
|
|
249
|
+
* @param options Optional settings.
|
|
250
|
+
* @param options.removeKeys Also remove any associated private key from the vault.
|
|
121
251
|
* @param controller The controller of the identity who can make changes.
|
|
122
252
|
* @returns A promise that resolves when the verification method has been removed.
|
|
123
253
|
* @throws NotFoundError if the id can not be resolved.
|
|
124
254
|
* @throws NotSupportedError if the platform does not support multiple revocable keys.
|
|
125
255
|
*/
|
|
126
|
-
async verificationMethodRemove(verificationMethodId, controller) {
|
|
256
|
+
async verificationMethodRemove(verificationMethodId, options, controller) {
|
|
127
257
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
128
258
|
Urn.guard(IdentityService.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
259
|
+
await TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerificationMethodRemove, { attributes: { [IdentitySpanAttributes.VerificationMethodId]: verificationMethodId } }, async () => {
|
|
260
|
+
try {
|
|
261
|
+
const idParts = DocumentHelper.parseId(verificationMethodId);
|
|
262
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
263
|
+
await identityConnector.removeVerificationMethod(controller, verificationMethodId, options);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verificationMethodRemoveFailed", { verificationMethodId }, error);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
137
269
|
}
|
|
138
270
|
/**
|
|
139
271
|
* Add a service to the document.
|
|
@@ -161,14 +293,16 @@ export class IdentityService {
|
|
|
161
293
|
else {
|
|
162
294
|
Guards.stringValue(IdentityService.CLASS_NAME, "serviceEndpoint", serviceEndpoint);
|
|
163
295
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
296
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.ServiceCreate, { attributes: { [IdentitySpanAttributes.Id]: identity } }, async () => {
|
|
297
|
+
try {
|
|
298
|
+
const identityConnector = this.getConnectorByUri(identity);
|
|
299
|
+
const service = await identityConnector.addService(controller, identity, serviceId, serviceType, serviceEndpoint);
|
|
300
|
+
return service;
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "serviceCreateFailed", { identity, serviceId }, error);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
172
306
|
}
|
|
173
307
|
/**
|
|
174
308
|
* Remove a service from the document.
|
|
@@ -180,14 +314,16 @@ export class IdentityService {
|
|
|
180
314
|
async serviceRemove(serviceId, controller) {
|
|
181
315
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
182
316
|
Urn.guard(IdentityService.CLASS_NAME, "serviceId", serviceId);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
317
|
+
await TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.ServiceRemove, { attributes: { [IdentitySpanAttributes.ServiceId]: serviceId } }, async () => {
|
|
318
|
+
try {
|
|
319
|
+
const idParts = DocumentHelper.parseId(serviceId);
|
|
320
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
321
|
+
await identityConnector.removeService(controller, serviceId);
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "serviceRemoveFailed", { serviceId }, error);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
191
327
|
}
|
|
192
328
|
/**
|
|
193
329
|
* Add an alias to the alsoKnownAs property on the document.
|
|
@@ -203,14 +339,16 @@ export class IdentityService {
|
|
|
203
339
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
204
340
|
Guards.stringValue(IdentityService.CLASS_NAME, "documentId", documentId);
|
|
205
341
|
Guards.stringValue(IdentityService.CLASS_NAME, "alias", alias);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
342
|
+
await TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.AlsoKnownAsAdd, { attributes: { [IdentitySpanAttributes.Id]: documentId } }, async () => {
|
|
343
|
+
try {
|
|
344
|
+
const idParts = DocumentHelper.parseId(documentId);
|
|
345
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
346
|
+
await identityConnector.addAlsoKnownAs(controller, documentId, alias);
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "alsoKnownAsAddFailed", { identity: documentId, alias }, error);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
214
352
|
}
|
|
215
353
|
/**
|
|
216
354
|
* Remove an alias from the alsoKnownAs property on the document.
|
|
@@ -226,14 +364,16 @@ export class IdentityService {
|
|
|
226
364
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
227
365
|
Guards.stringValue(IdentityService.CLASS_NAME, "documentId", documentId);
|
|
228
366
|
Guards.stringValue(IdentityService.CLASS_NAME, "alias", alias);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
367
|
+
await TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.AlsoKnownAsRemove, { attributes: { [IdentitySpanAttributes.Id]: documentId } }, async () => {
|
|
368
|
+
try {
|
|
369
|
+
const idParts = DocumentHelper.parseId(documentId);
|
|
370
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
371
|
+
await identityConnector.removeAlsoKnownAs(controller, documentId, alias);
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "alsoKnownAsRemoveFailed", { identity: documentId, alias }, error);
|
|
375
|
+
}
|
|
376
|
+
});
|
|
237
377
|
}
|
|
238
378
|
/**
|
|
239
379
|
* Create a verifiable credential for a verification method.
|
|
@@ -253,19 +393,21 @@ export class IdentityService {
|
|
|
253
393
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
254
394
|
Urn.guard(IdentityService.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
255
395
|
Guards.object(IdentityService.CLASS_NAME, "subject", subject);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
396
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiableCredentialCreate, { attributes: { [IdentitySpanAttributes.VerificationMethodId]: verificationMethodId } }, async () => {
|
|
397
|
+
try {
|
|
398
|
+
const idParts = DocumentHelper.parseId(verificationMethodId);
|
|
399
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
400
|
+
const service = await identityConnector.createVerifiableCredential(controller, verificationMethodId, id, subject, options);
|
|
401
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsCreated, {
|
|
402
|
+
hasRevocation: Is.number(options?.revocationIndex),
|
|
403
|
+
hasExpiration: Is.date(options?.expirationDate)
|
|
404
|
+
});
|
|
405
|
+
return service;
|
|
406
|
+
}
|
|
407
|
+
catch (error) {
|
|
408
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialCreateFailed", { verificationMethodId }, error);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
269
411
|
}
|
|
270
412
|
/**
|
|
271
413
|
* Verify a verifiable credential is valid.
|
|
@@ -277,20 +419,24 @@ export class IdentityService {
|
|
|
277
419
|
Guards.objectValue(IdentityService.CLASS_NAME, "credential", credential);
|
|
278
420
|
Guards.stringValue(IdentityService.CLASS_NAME, "credential.issuer", credential.issuer);
|
|
279
421
|
Guards.objectValue(IdentityService.CLASS_NAME, "credential.proof", credential.proof);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
422
|
+
const issuer = credential.issuer;
|
|
423
|
+
const verifiableCredential = credential;
|
|
424
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiableCredentialVerify, undefined, async () => {
|
|
425
|
+
try {
|
|
426
|
+
const identityConnector = this.getConnectorByUri(issuer);
|
|
427
|
+
const service = await identityConnector.checkVerifiableCredential(verifiableCredential);
|
|
428
|
+
if (service.revoked) {
|
|
429
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsVerificationFailed, { failureReason: "revoked" });
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsVerified);
|
|
433
|
+
}
|
|
434
|
+
return service;
|
|
285
435
|
}
|
|
286
|
-
|
|
287
|
-
|
|
436
|
+
catch (error) {
|
|
437
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialVerifyFailed", undefined, error);
|
|
288
438
|
}
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
catch (error) {
|
|
292
|
-
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialVerifyFailed", undefined, error);
|
|
293
|
-
}
|
|
439
|
+
});
|
|
294
440
|
}
|
|
295
441
|
Guards.stringValue(IdentityService.CLASS_NAME, "credential", credential);
|
|
296
442
|
const jwtDecoded = await Jwt.decode(credential);
|
|
@@ -303,20 +449,23 @@ export class IdentityService {
|
|
|
303
449
|
Is.undefined(jwtSignature)) {
|
|
304
450
|
throw new GeneralError(IdentityService.CLASS_NAME, "jwtDecodeFailed");
|
|
305
451
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
await
|
|
452
|
+
const issuer = jwtPayload.iss;
|
|
453
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiableCredentialVerify, undefined, async () => {
|
|
454
|
+
try {
|
|
455
|
+
const identityConnector = this.getConnectorByUri(issuer);
|
|
456
|
+
const service = await identityConnector.checkVerifiableCredential(credential);
|
|
457
|
+
if (service.revoked) {
|
|
458
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsVerificationFailed, { failureReason: "revoked" });
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsVerified);
|
|
462
|
+
}
|
|
463
|
+
return service;
|
|
311
464
|
}
|
|
312
|
-
|
|
313
|
-
|
|
465
|
+
catch (error) {
|
|
466
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialVerifyFailed", undefined, error);
|
|
314
467
|
}
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
catch (error) {
|
|
318
|
-
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialVerifyFailed", undefined, error);
|
|
319
|
-
}
|
|
468
|
+
});
|
|
320
469
|
}
|
|
321
470
|
/**
|
|
322
471
|
* Revoke verifiable credential.
|
|
@@ -329,16 +478,18 @@ export class IdentityService {
|
|
|
329
478
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
330
479
|
Guards.stringValue(IdentityService.CLASS_NAME, "issuerIdentity", issuerIdentity);
|
|
331
480
|
Guards.number(IdentityService.CLASS_NAME, "credentialIndex", credentialIndex);
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
481
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiableCredentialRevoke, { attributes: { [IdentitySpanAttributes.Id]: issuerIdentity } }, async () => {
|
|
482
|
+
try {
|
|
483
|
+
const idParts = DocumentHelper.parseId(issuerIdentity);
|
|
484
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
485
|
+
const result = await identityConnector.revokeVerifiableCredentials(controller, issuerIdentity, [credentialIndex]);
|
|
486
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsRevoked);
|
|
487
|
+
return result;
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialRevokeFailed", { issuerIdentity, credentialIndex }, error);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
342
493
|
}
|
|
343
494
|
/**
|
|
344
495
|
* Unrevoke verifiable credential.
|
|
@@ -351,16 +502,18 @@ export class IdentityService {
|
|
|
351
502
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
352
503
|
Guards.stringValue(IdentityService.CLASS_NAME, "issuerIdentity", issuerIdentity);
|
|
353
504
|
Guards.number(IdentityService.CLASS_NAME, "credentialIndex", credentialIndex);
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
505
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiableCredentialUnrevoke, { attributes: { [IdentitySpanAttributes.Id]: issuerIdentity } }, async () => {
|
|
506
|
+
try {
|
|
507
|
+
const idParts = DocumentHelper.parseId(issuerIdentity);
|
|
508
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
509
|
+
const result = await identityConnector.unrevokeVerifiableCredentials(controller, issuerIdentity, [credentialIndex]);
|
|
510
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VcsUnrevoked);
|
|
511
|
+
return result;
|
|
512
|
+
}
|
|
513
|
+
catch (error) {
|
|
514
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiableCredentialUnrevokeFailed", { issuerIdentity, credentialIndex }, error);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
364
517
|
}
|
|
365
518
|
/**
|
|
366
519
|
* Create a verifiable presentation from the supplied verifiable credentials.
|
|
@@ -380,18 +533,20 @@ export class IdentityService {
|
|
|
380
533
|
async verifiablePresentationCreate(verificationMethodId, presentationId, contexts, types, verifiableCredentials, options, controller) {
|
|
381
534
|
Guards.stringValue(IdentityService.CLASS_NAME, "controller", controller);
|
|
382
535
|
Guards.stringValue(IdentityService.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
536
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiablePresentationCreate, { attributes: { [IdentitySpanAttributes.VerificationMethodId]: verificationMethodId } }, async () => {
|
|
537
|
+
try {
|
|
538
|
+
const idParts = DocumentHelper.parseId(verificationMethodId);
|
|
539
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
540
|
+
const result = await identityConnector.createVerifiablePresentation(controller, verificationMethodId, presentationId, contexts, types, verifiableCredentials, options);
|
|
541
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VpsCreated, {
|
|
542
|
+
credentialCount: verifiableCredentials.length
|
|
543
|
+
});
|
|
544
|
+
return result;
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiablePresentationCreateFailed", { verificationMethodId }, error);
|
|
548
|
+
}
|
|
549
|
+
});
|
|
395
550
|
}
|
|
396
551
|
/**
|
|
397
552
|
* Verify a verifiable presentation is valid.
|
|
@@ -418,20 +573,22 @@ export class IdentityService {
|
|
|
418
573
|
holder = presentation.holder;
|
|
419
574
|
}
|
|
420
575
|
Guards.stringValue(IdentityService.CLASS_NAME, "holder", holder);
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
576
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.VerifiablePresentationVerify, undefined, async () => {
|
|
577
|
+
try {
|
|
578
|
+
const identityConnector = this.getConnectorByUri(holder);
|
|
579
|
+
const service = await identityConnector.checkVerifiablePresentation(presentation);
|
|
580
|
+
if (service.revoked) {
|
|
581
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VpsVerificationFailed, { failureReason: "revoked" });
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, IdentityMetricIds.VpsVerified);
|
|
585
|
+
}
|
|
586
|
+
return service;
|
|
426
587
|
}
|
|
427
|
-
|
|
428
|
-
|
|
588
|
+
catch (error) {
|
|
589
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "verifiablePresentationVerifyFailed", undefined, error);
|
|
429
590
|
}
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
catch (error) {
|
|
433
|
-
throw new GeneralError(IdentityService.CLASS_NAME, "verifiablePresentationVerifyFailed", undefined, error);
|
|
434
|
-
}
|
|
591
|
+
});
|
|
435
592
|
}
|
|
436
593
|
/**
|
|
437
594
|
* Create a proof for a document with the specified verification method.
|
|
@@ -446,15 +603,17 @@ export class IdentityService {
|
|
|
446
603
|
Guards.stringValue(IdentityService.CLASS_NAME, "verificationMethodId", verificationMethodId);
|
|
447
604
|
Guards.arrayOneOf(IdentityService.CLASS_NAME, "proofType", proofType, Object.values(ProofTypes));
|
|
448
605
|
Guards.object(IdentityService.CLASS_NAME, "unsecureDocument", unsecureDocument);
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
606
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.ProofCreate, { attributes: { [IdentitySpanAttributes.VerificationMethodId]: verificationMethodId } }, async () => {
|
|
607
|
+
try {
|
|
608
|
+
const idParts = DocumentHelper.parseId(verificationMethodId);
|
|
609
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
610
|
+
const result = await identityConnector.createProof(controller, verificationMethodId, proofType, unsecureDocument);
|
|
611
|
+
return result;
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "proofCreateFailed", { verificationMethodId }, error);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
458
617
|
}
|
|
459
618
|
/**
|
|
460
619
|
* Verify proof for a document with the specified verification method.
|
|
@@ -466,15 +625,18 @@ export class IdentityService {
|
|
|
466
625
|
Guards.object(IdentityService.CLASS_NAME, "document", document);
|
|
467
626
|
Guards.object(IdentityService.CLASS_NAME, "proof", proof);
|
|
468
627
|
Guards.stringValue(IdentityService.CLASS_NAME, "proof.verificationMethod", proof.verificationMethod);
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
628
|
+
const verificationMethod = proof.verificationMethod;
|
|
629
|
+
return TracingHelper.withSpan(this._tracingComponent, IdentitySpanNames.ProofVerify, undefined, async () => {
|
|
630
|
+
try {
|
|
631
|
+
const idParts = DocumentHelper.parseId(verificationMethod);
|
|
632
|
+
const identityConnector = this.getConnectorByUri(idParts.id);
|
|
633
|
+
const result = await identityConnector.verifyProof(document, proof);
|
|
634
|
+
return result;
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
throw new GeneralError(IdentityService.CLASS_NAME, "proofVerifyFailed", undefined, error);
|
|
638
|
+
}
|
|
639
|
+
});
|
|
478
640
|
}
|
|
479
641
|
/**
|
|
480
642
|
* Get the connector from the namespace.
|