@cef-ebsi/cli 0.0.0-alpha.0

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 (159) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +32 -0
  3. package/bin/cli.js +13 -0
  4. package/dist/abi/pilot/DidRegistry-old.json +2192 -0
  5. package/dist/abi/pilot/DidRegistry.json +1081 -0
  6. package/dist/abi/pilot/DidRegistryV3.json +1081 -0
  7. package/dist/abi/pilot/SchemaSCRegistry.json +972 -0
  8. package/dist/abi/pilot/SchemaSCRegistryV2.json +473 -0
  9. package/dist/abi/pilot/Tar.json +1394 -0
  10. package/dist/abi/pilot/TarV3.json +1107 -0
  11. package/dist/abi/pilot/Timestamp.json +1091 -0
  12. package/dist/abi/pilot/TimestampV2.json +1127 -0
  13. package/dist/abi/pilot/Tir.json +896 -0
  14. package/dist/abi/pilot/TirV3.json +495 -0
  15. package/dist/abi/pilot/Tpr.json +1267 -0
  16. package/dist/abi/pilot/TprV2.json +888 -0
  17. package/dist/abi/test/DidRegistry-old.json +2192 -0
  18. package/dist/abi/test/DidRegistry.json +1081 -0
  19. package/dist/abi/test/DidRegistryV3.json +1088 -0
  20. package/dist/abi/test/SchemaSCRegistry.json +972 -0
  21. package/dist/abi/test/SchemaSCRegistryV2.json +473 -0
  22. package/dist/abi/test/Tar.json +1394 -0
  23. package/dist/abi/test/TarV3.json +1107 -0
  24. package/dist/abi/test/Timestamp.json +1091 -0
  25. package/dist/abi/test/TimestampV2.json +1127 -0
  26. package/dist/abi/test/Tir.json +896 -0
  27. package/dist/abi/test/TirV3.json +495 -0
  28. package/dist/abi/test/Tpr.json +1267 -0
  29. package/dist/abi/test/TprV2.json +888 -0
  30. package/dist/app.js +1205 -0
  31. package/dist/app.js.map +1 -0
  32. package/dist/buildParam/did.js +355 -0
  33. package/dist/buildParam/did.js.map +1 -0
  34. package/dist/buildParam/didOld.js +275 -0
  35. package/dist/buildParam/didOld.js.map +1 -0
  36. package/dist/buildParam/didV3.js +353 -0
  37. package/dist/buildParam/didV3.js.map +1 -0
  38. package/dist/buildParam/index.js +54 -0
  39. package/dist/buildParam/index.js.map +1 -0
  40. package/dist/buildParam/tar.js +240 -0
  41. package/dist/buildParam/tar.js.map +1 -0
  42. package/dist/buildParam/tarV3.js +193 -0
  43. package/dist/buildParam/tarV3.js.map +1 -0
  44. package/dist/buildParam/timestamp.js +323 -0
  45. package/dist/buildParam/timestamp.js.map +1 -0
  46. package/dist/buildParam/timestampV2.js +317 -0
  47. package/dist/buildParam/timestampV2.js.map +1 -0
  48. package/dist/buildParam/tir.js +200 -0
  49. package/dist/buildParam/tir.js.map +1 -0
  50. package/dist/buildParam/tirV3.js +104 -0
  51. package/dist/buildParam/tirV3.js.map +1 -0
  52. package/dist/buildParam/tpr.js +167 -0
  53. package/dist/buildParam/tpr.js.map +1 -0
  54. package/dist/buildParam/tprV2.js +82 -0
  55. package/dist/buildParam/tprV2.js.map +1 -0
  56. package/dist/buildParam/tsr.js +149 -0
  57. package/dist/buildParam/tsr.js.map +1 -0
  58. package/dist/buildParam/tsrV2.js +110 -0
  59. package/dist/buildParam/tsrV2.js.map +1 -0
  60. package/dist/cli.js +10 -0
  61. package/dist/cli.js.map +1 -0
  62. package/dist/commands/authorisation-v3.js +98 -0
  63. package/dist/commands/authorisation-v3.js.map +1 -0
  64. package/dist/commands/authorisation-v4.js +221 -0
  65. package/dist/commands/authorisation-v4.js.map +1 -0
  66. package/dist/commands/compute.js +374 -0
  67. package/dist/commands/compute.js.map +1 -0
  68. package/dist/commands/conformance-v3.js +745 -0
  69. package/dist/commands/conformance-v3.js.map +1 -0
  70. package/dist/commands/conformance-v4.js +767 -0
  71. package/dist/commands/conformance-v4.js.map +1 -0
  72. package/dist/commands/index.js +9 -0
  73. package/dist/commands/index.js.map +1 -0
  74. package/dist/commands/ledger-v3.js +189 -0
  75. package/dist/commands/ledger-v3.js.map +1 -0
  76. package/dist/commands/ledger-v4.js +188 -0
  77. package/dist/commands/ledger-v4.js.map +1 -0
  78. package/dist/commands/view.js +62 -0
  79. package/dist/commands/view.js.map +1 -0
  80. package/dist/config.js +910 -0
  81. package/dist/config.js.map +1 -0
  82. package/dist/index.js +7 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/interfaces/authorisation/authorisation.interface.js +2 -0
  85. package/dist/interfaces/authorisation/authorisation.interface.js.map +1 -0
  86. package/dist/interfaces/authorisation/index.js +2 -0
  87. package/dist/interfaces/authorisation/index.js.map +1 -0
  88. package/dist/interfaces/context.js +2 -0
  89. package/dist/interfaces/context.js.map +1 -0
  90. package/dist/interfaces/index.js +10 -0
  91. package/dist/interfaces/index.js.map +1 -0
  92. package/dist/interfaces/ledger/besu.interface.js +2 -0
  93. package/dist/interfaces/ledger/besu.interface.js.map +1 -0
  94. package/dist/interfaces/ledger/index.js +2 -0
  95. package/dist/interfaces/ledger/index.js.map +1 -0
  96. package/dist/interfaces/notifications/index.js +2 -0
  97. package/dist/interfaces/notifications/index.js.map +1 -0
  98. package/dist/interfaces/notifications/notifications.interface.js +2 -0
  99. package/dist/interfaces/notifications/notifications.interface.js.map +1 -0
  100. package/dist/interfaces/proxy-data-hub/attributes.interface.js +2 -0
  101. package/dist/interfaces/proxy-data-hub/attributes.interface.js.map +1 -0
  102. package/dist/interfaces/proxy-data-hub/index.js +2 -0
  103. package/dist/interfaces/proxy-data-hub/index.js.map +1 -0
  104. package/dist/interfaces/shared/index.js +5 -0
  105. package/dist/interfaces/shared/index.js.map +1 -0
  106. package/dist/interfaces/shared/jsonrpc.interface.js +2 -0
  107. package/dist/interfaces/shared/jsonrpc.interface.js.map +1 -0
  108. package/dist/interfaces/shared/paginated-list.interface.js +2 -0
  109. package/dist/interfaces/shared/paginated-list.interface.js.map +1 -0
  110. package/dist/interfaces/shared/unsigned-transaction.interface.js +2 -0
  111. package/dist/interfaces/shared/unsigned-transaction.interface.js.map +1 -0
  112. package/dist/interfaces/shared/utils.interface.js +2 -0
  113. package/dist/interfaces/shared/utils.interface.js.map +1 -0
  114. package/dist/interfaces/timestamp/hash-algorithms.interface.js +2 -0
  115. package/dist/interfaces/timestamp/hash-algorithms.interface.js.map +1 -0
  116. package/dist/interfaces/timestamp/index.js +4 -0
  117. package/dist/interfaces/timestamp/index.js.map +1 -0
  118. package/dist/interfaces/timestamp/records.interface.js +2 -0
  119. package/dist/interfaces/timestamp/records.interface.js.map +1 -0
  120. package/dist/interfaces/timestamp/timestamps.interface.js +2 -0
  121. package/dist/interfaces/timestamp/timestamps.interface.js.map +1 -0
  122. package/dist/interfaces/trusted-apps-registry/apps.interface.js +2 -0
  123. package/dist/interfaces/trusted-apps-registry/apps.interface.js.map +1 -0
  124. package/dist/interfaces/trusted-apps-registry/index.js +3 -0
  125. package/dist/interfaces/trusted-apps-registry/index.js.map +1 -0
  126. package/dist/interfaces/trusted-apps-registry/policies.interface.js +2 -0
  127. package/dist/interfaces/trusted-apps-registry/policies.interface.js.map +1 -0
  128. package/dist/interfaces/trusted-issuers-registry/index.js +2 -0
  129. package/dist/interfaces/trusted-issuers-registry/index.js.map +1 -0
  130. package/dist/interfaces/trusted-issuers-registry/issuers.interface.js +2 -0
  131. package/dist/interfaces/trusted-issuers-registry/issuers.interface.js.map +1 -0
  132. package/dist/interfaces/users-onboarding/authentication.js +2 -0
  133. package/dist/interfaces/users-onboarding/authentication.js.map +1 -0
  134. package/dist/interfaces/users-onboarding/index.js +2 -0
  135. package/dist/interfaces/users-onboarding/index.js.map +1 -0
  136. package/dist/programs/appRegistration.js +65 -0
  137. package/dist/programs/appRegistration.js.map +1 -0
  138. package/dist/tsconfig.tsbuildinfo +1 -0
  139. package/dist/utils/Client.js +176 -0
  140. package/dist/utils/Client.js.map +1 -0
  141. package/dist/utils/authorisation.js +118 -0
  142. package/dist/utils/authorisation.js.map +1 -0
  143. package/dist/utils/http.js +128 -0
  144. package/dist/utils/http.js.map +1 -0
  145. package/dist/utils/index.js +10 -0
  146. package/dist/utils/index.js.map +1 -0
  147. package/dist/utils/jsonrpc.js +33 -0
  148. package/dist/utils/jsonrpc.js.map +1 -0
  149. package/dist/utils/notification.js +51 -0
  150. package/dist/utils/notification.js.map +1 -0
  151. package/dist/utils/print.js +57 -0
  152. package/dist/utils/print.js.map +1 -0
  153. package/dist/utils/storage.js +97 -0
  154. package/dist/utils/storage.js.map +1 -0
  155. package/dist/utils/utils.js +161 -0
  156. package/dist/utils/utils.js.map +1 -0
  157. package/dist/utils/verifiablePresentation.js +43 -0
  158. package/dist/utils/verifiablePresentation.js.map +1 -0
  159. package/package.json +113 -0
@@ -0,0 +1,745 @@
1
+ import { randomUUID, randomBytes, createHash } from "node:crypto";
2
+ import { URLSearchParams } from "node:url";
3
+ import Joi from "joi";
4
+ import qs from "qs";
5
+ import { base64url } from "multiformats/bases/base64";
6
+ import { importJWK, SignJWT } from "jose";
7
+ import { compute, getUserPin } from "./compute.js";
8
+ import { httpCall, red } from "../utils/index.js";
9
+ function stringify(obj, fields) {
10
+ if (typeof obj !== "object")
11
+ throw new Error("not an object");
12
+ const newObj = {};
13
+ fields.forEach((f) => {
14
+ if (obj[f])
15
+ newObj[f] = obj[f];
16
+ });
17
+ return JSON.stringify(newObj);
18
+ }
19
+ async function conformanceGet(inputs, context) {
20
+ const apiUrl = context.config.api.conformance.url;
21
+ const urlPath = inputs.join("");
22
+ const url = urlPath.startsWith("http") ? urlPath : `${apiUrl}${urlPath}`;
23
+ const response = await httpCall.get(url, context.httpOpts);
24
+ return response.data;
25
+ }
26
+ async function clientMockInitiate(context) {
27
+ const apiUrl = context.config.api.conformance.url;
28
+ const { accreditationUrl, proxyId, issuerState } = context.rtVars.user;
29
+ const response = await httpCall.post(`${apiUrl}/client-mock/initiate`, {
30
+ did: context.client.did,
31
+ keys: Object.keys(context.client.keys).map((keyName) => {
32
+ const key = context.client.keys[keyName];
33
+ return {
34
+ ...key.privateKeyJwk,
35
+ kid: key.id,
36
+ };
37
+ }),
38
+ ...(accreditationUrl && { attributeUrl: accreditationUrl }),
39
+ ...(proxyId && { proxyId }),
40
+ ...(issuerState && { issuerState }),
41
+ });
42
+ context.client.clientId = `${apiUrl}/client-mock/${context.client.did}`;
43
+ context.rtVars.user.clientId =
44
+ context.client.clientId;
45
+ return response.data;
46
+ }
47
+ async function clientMockUpdateList(inputs, context) {
48
+ const [statusIndex, statusListIndex, value] = inputs;
49
+ const apiUrl = context.config.api.conformance.url;
50
+ const response = await httpCall.post(`${apiUrl}/client-mock/updateList`, {
51
+ did: context.client.did,
52
+ id: statusIndex,
53
+ position: Number(statusListIndex),
54
+ value: Number(value),
55
+ });
56
+ return response.data;
57
+ }
58
+ async function authMockAuthorize(inputs, context) {
59
+ const [openIdCredentialIssuer, openIdConfiguration, requestedTypes, inputAlg, codeVerifier, issuerState,] = inputs;
60
+ const alg = inputAlg || "ES256";
61
+ Joi.assert(requestedTypes, Joi.array());
62
+ Joi.assert(alg, Joi.string().valid("ES256K", "ES256", "EdDSA", "RS256"));
63
+ const isPKCEChallenge = !!codeVerifier;
64
+ const authorizationServer = openIdCredentialIssuer.authorization_server ??
65
+ openIdCredentialIssuer.credential_issuer;
66
+ const clientId = context.client.didVersion === 1
67
+ ? context.client.clientId
68
+ : context.client.did;
69
+ let codeChallenge = "";
70
+ if (isPKCEChallenge) {
71
+ codeChallenge = base64url.baseEncode(createHash("sha256").update(codeVerifier).digest());
72
+ }
73
+ const clientMetadata = isPKCEChallenge
74
+ ? {
75
+ authorization_endpoint: "openid:",
76
+ }
77
+ : {
78
+ redirect_uris: [`${context.client.clientId}/code-cb`],
79
+ jwks_uri: `${context.client.clientId}/jwks`,
80
+ authorization_endpoint: `${context.client.clientId}/authorize`,
81
+ };
82
+ const authorizationDetails = [
83
+ {
84
+ type: "openid_credential",
85
+ format: "jwt_vc",
86
+ locations: [openIdCredentialIssuer.credential_issuer],
87
+ types: requestedTypes,
88
+ },
89
+ ];
90
+ const queryParams = {
91
+ scope: "openid",
92
+ client_id: clientId,
93
+ client_metadata: JSON.stringify(clientMetadata),
94
+ redirect_uri: isPKCEChallenge
95
+ ? "openid://callback"
96
+ : `${context.client.clientId}/code-cb`,
97
+ response_type: "code",
98
+ state: randomUUID(),
99
+ ...(isPKCEChallenge && {
100
+ code_challenge: codeChallenge,
101
+ code_challenge_method: "S256",
102
+ }),
103
+ ...(issuerState && { issuer_state: issuerState }),
104
+ authorization_details: JSON.stringify(authorizationDetails),
105
+ };
106
+ const jwtPayload = {
107
+ ...queryParams,
108
+ client_metadata: clientMetadata,
109
+ authorization_details: authorizationDetails,
110
+ };
111
+ const clientPrivateKey = await importJWK(context.client.keys[alg].privateKeyJwk, alg);
112
+ const requestParam = await new SignJWT(jwtPayload)
113
+ .setProtectedHeader({
114
+ typ: "JWT",
115
+ alg,
116
+ kid: isPKCEChallenge
117
+ ? context.client.keys[alg].kid
118
+ : context.client.keys[alg].id,
119
+ })
120
+ .setIssuer(clientId)
121
+ .setAudience(authorizationServer)
122
+ .sign(clientPrivateKey);
123
+ const responseAuthorize = await httpCall.get(`${openIdConfiguration.authorization_endpoint}?${new URLSearchParams({
124
+ ...queryParams,
125
+ request: requestParam,
126
+ }).toString()}`);
127
+ const { location } = responseAuthorize.headers;
128
+ const locationUrl = new URL(location);
129
+ if (locationUrl.searchParams.get("error"))
130
+ throw new Error(locationUrl.searchParams.toString());
131
+ const responseQueryParams = qs.parse(locationUrl.search.substring(1));
132
+ return responseQueryParams;
133
+ }
134
+ async function authMockDirectPostIdToken(inputs, context) {
135
+ const [openIdCredentialIssuer, openIdConfiguration, issuerRequest, inputAlg] = inputs;
136
+ const alg = inputAlg || "ES256";
137
+ Joi.assert(alg, Joi.string().valid("ES256K", "ES256", "EdDSA", "RS256"));
138
+ const authorizationServer = openIdCredentialIssuer.authorization_server ??
139
+ openIdCredentialIssuer.credential_issuer;
140
+ const { state, nonce } = issuerRequest;
141
+ const clientPrivateKey = await importJWK(context.client.keys[alg].privateKeyJwk, alg);
142
+ const idTokenDirectPost = await new SignJWT({
143
+ nonce,
144
+ sub: context.client.did,
145
+ })
146
+ .setProtectedHeader({
147
+ typ: "JWT",
148
+ alg,
149
+ kid: context.client.keys[alg].kid,
150
+ })
151
+ .setIssuer(context.client.did)
152
+ .setAudience(authorizationServer)
153
+ .setIssuedAt()
154
+ .setExpirationTime("5m")
155
+ .sign(clientPrivateKey);
156
+ const responseDirectPost = await httpCall.post(openIdConfiguration.redirect_uris[0], new URLSearchParams({
157
+ id_token: idTokenDirectPost,
158
+ state,
159
+ }).toString(), {
160
+ headers: {
161
+ "content-type": "application/x-www-form-urlencoded",
162
+ },
163
+ });
164
+ const { location } = responseDirectPost.headers;
165
+ const locationUrl = new URL(location);
166
+ if (locationUrl.searchParams.get("error"))
167
+ throw new Error(locationUrl.searchParams.toString());
168
+ const responseQueryParams = qs.parse(locationUrl.search.substring(1));
169
+ return responseQueryParams;
170
+ }
171
+ async function authMockDirectPostVpToken(inputs) {
172
+ const [openIdConfiguration, issuerRequest, vpJwt, type] = inputs;
173
+ const { state } = issuerRequest;
174
+ const presentationSubmission = type === "holder"
175
+ ? {
176
+ id: randomUUID(),
177
+ definition_id: "holder-wallet-qualification-presentation",
178
+ descriptor_map: [
179
+ {
180
+ id: "same-device-in-time-credential",
181
+ path: "$",
182
+ format: "jwt_vp",
183
+ path_nested: {
184
+ id: "same-device-in-time-credential",
185
+ format: "jwt_vc",
186
+ path: "$.verifiableCredential[0]",
187
+ },
188
+ },
189
+ {
190
+ id: "cross-device-in-time-credential",
191
+ path: "$",
192
+ format: "jwt_vp",
193
+ path_nested: {
194
+ id: "cross-device-in-time-credential",
195
+ format: "jwt_vc",
196
+ path: "$.verifiableCredential[1]",
197
+ },
198
+ },
199
+ {
200
+ id: "same-device-deferred-credential",
201
+ path: "$",
202
+ format: "jwt_vp",
203
+ path_nested: {
204
+ id: "same-device-deferred-credential",
205
+ format: "jwt_vc",
206
+ path: "$.verifiableCredential[2]",
207
+ },
208
+ },
209
+ {
210
+ id: "cross-device-deferred-credential",
211
+ path: "$",
212
+ format: "jwt_vp",
213
+ path_nested: {
214
+ id: "cross-device-deferred-credential",
215
+ format: "jwt_vc",
216
+ path: "$.verifiableCredential[3]",
217
+ },
218
+ },
219
+ {
220
+ id: "same-device-pre_authorised-credential",
221
+ path: "$",
222
+ format: "jwt_vp",
223
+ path_nested: {
224
+ id: "same-device-pre_authorised-credential",
225
+ format: "jwt_vc",
226
+ path: "$.verifiableCredential[4]",
227
+ },
228
+ },
229
+ {
230
+ id: "cross-device-pre_authorised-credential",
231
+ path: "$",
232
+ format: "jwt_vp",
233
+ path_nested: {
234
+ id: "cross-device-pre_authorised-credential",
235
+ format: "jwt_vc",
236
+ path: "$.verifiableCredential[5]",
237
+ },
238
+ },
239
+ ],
240
+ }
241
+ : {
242
+ id: randomUUID(),
243
+ definition_id: "va-to-onboard-presentation",
244
+ descriptor_map: [
245
+ {
246
+ id: "verifiable-authorisation-to-onboard",
247
+ format: "jwt_vp",
248
+ path: "$",
249
+ path_nested: {
250
+ id: "verifiable-authorisation-to-onboard",
251
+ format: "jwt_vc",
252
+ path: "$.verifiableCredential[0]",
253
+ },
254
+ },
255
+ ],
256
+ };
257
+ const responseDirectPost = await httpCall.post(openIdConfiguration.redirect_uris[0], new URLSearchParams({
258
+ vp_token: vpJwt,
259
+ state,
260
+ presentation_submission: JSON.stringify(presentationSubmission),
261
+ }).toString(), {
262
+ headers: {
263
+ "Content-Type": "application/x-www-form-urlencoded",
264
+ },
265
+ });
266
+ const { location } = responseDirectPost.headers;
267
+ const locationUrl = new URL(location);
268
+ if (locationUrl.searchParams.get("error"))
269
+ throw new Error(locationUrl.searchParams.toString());
270
+ const responseQueryParams = qs.parse(locationUrl.search.substring(1));
271
+ return responseQueryParams;
272
+ }
273
+ async function authMockToken(inputs, context) {
274
+ const [openIdCredentialIssuer, openIdConfiguration, code, inputAlg, codeVerifier, type,] = inputs;
275
+ const alg = inputAlg || "ES256";
276
+ const isPKCEChallenge = !!codeVerifier;
277
+ const authorizationServer = openIdCredentialIssuer.authorization_server ??
278
+ openIdCredentialIssuer.credential_issuer;
279
+ let queryParams;
280
+ if (type === "preAuthorised") {
281
+ queryParams = {
282
+ grant_type: "urn:ietf:params:oauth:grant-type:pre-authorized_code",
283
+ "pre-authorized_code": code,
284
+ user_pin: getUserPin(context.client.did),
285
+ };
286
+ }
287
+ else {
288
+ queryParams = {
289
+ grant_type: "authorization_code",
290
+ code,
291
+ client_id: isPKCEChallenge ? context.client.did : context.client.clientId,
292
+ ...(!isPKCEChallenge && {
293
+ client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
294
+ }),
295
+ ...(isPKCEChallenge && {
296
+ code_verifier: codeVerifier,
297
+ }),
298
+ };
299
+ }
300
+ const jwtPayload = {
301
+ ...queryParams,
302
+ };
303
+ const clientPrivateKey = await importJWK(context.client.keys[alg].privateKeyJwk, alg);
304
+ const clientAssertion = await new SignJWT(jwtPayload)
305
+ .setProtectedHeader({
306
+ typ: "JWT",
307
+ alg,
308
+ kid: context.client.keys[alg].id,
309
+ })
310
+ .setIssuer(context.client.clientId)
311
+ .setAudience(authorizationServer)
312
+ .setSubject(context.client.clientId)
313
+ .setIssuedAt()
314
+ .setExpirationTime("5m")
315
+ .sign(clientPrivateKey);
316
+ const responseToken = await httpCall.post(openIdConfiguration.token_endpoint, new URLSearchParams({
317
+ ...queryParams,
318
+ client_assertion: clientAssertion,
319
+ }).toString(), {
320
+ headers: {
321
+ "content-type": "application/x-www-form-urlencoded",
322
+ },
323
+ });
324
+ return responseToken.data;
325
+ }
326
+ async function issuerMockCredential(inputs, context) {
327
+ const [openIdCredentialIssuer, nonce, requestedTypes, inputAlg] = inputs;
328
+ const alg = inputAlg || "ES256";
329
+ const clientId = context.client.didVersion === 1
330
+ ? context.client.clientId
331
+ : context.client.did;
332
+ const clientPrivateKey = await importJWK(context.client.keys[alg].privateKeyJwk, alg);
333
+ const proofJwt = await new SignJWT({ nonce })
334
+ .setProtectedHeader({
335
+ typ: "openid4vci-proof+jwt",
336
+ alg,
337
+ kid: context.client.keys[alg].kid,
338
+ })
339
+ .setIssuer(clientId)
340
+ .setAudience(openIdCredentialIssuer.credential_issuer)
341
+ .setIssuedAt()
342
+ .setExpirationTime("5m")
343
+ .sign(clientPrivateKey);
344
+ const responseCredential = await httpCall.post(`${openIdCredentialIssuer.credential_issuer}/credential`, {
345
+ types: requestedTypes,
346
+ format: "jwt_vc",
347
+ proof: {
348
+ proof_type: "jwt",
349
+ jwt: proofJwt,
350
+ },
351
+ }, context.httpOpts);
352
+ return responseCredential.data;
353
+ }
354
+ async function issuerMockDeferred(inputs) {
355
+ const [openIdCredentialIssuer, acceptanceToken] = inputs;
356
+ const response = await httpCall.post(openIdCredentialIssuer.deferred_credential_endpoint, undefined, {
357
+ headers: {
358
+ authorization: `Bearer ${acceptanceToken}`,
359
+ },
360
+ });
361
+ return response.data;
362
+ }
363
+ async function issuerMockInitiateCredentialOffer(inputs, context) {
364
+ const [initiateCredentialOfferEndpoint, credentialType] = inputs;
365
+ const requestParams = {
366
+ credential_type: credentialType,
367
+ credential_offer_endpoint: "openid-credential-offer://",
368
+ client_id: context.client.did,
369
+ };
370
+ let response = await httpCall.get(`${initiateCredentialOfferEndpoint}?${qs.stringify(requestParams)}`);
371
+ let search;
372
+ if (credentialType.startsWith("CTWalletSame")) {
373
+ search = new URL(response.headers.location)
374
+ .search;
375
+ }
376
+ else {
377
+ search = new URL(response.data).search;
378
+ }
379
+ const parsedCredentialOffer = qs.parse(search.slice(1));
380
+ if (parsedCredentialOffer.credential_offer_uri) {
381
+ response = await httpCall.get(parsedCredentialOffer.credential_offer_uri);
382
+ return response.data;
383
+ }
384
+ return qs.parse(parsedCredentialOffer.credential_offer);
385
+ }
386
+ async function getCredential(inputs, context) {
387
+ const [type, inputAlg, vc, inputIssuer] = inputs;
388
+ const alg = inputAlg || "ES256";
389
+ const openIdCredentialIssuerUrl = inputIssuer
390
+ ? `/client-mock/${inputIssuer}/.well-known/openid-credential-issuer`
391
+ : "/issuer-mock/.well-known/openid-credential-issuer";
392
+ let requestedTypes;
393
+ switch (type) {
394
+ case "onboard": {
395
+ requestedTypes = [
396
+ "VerifiableCredential",
397
+ "VerifiableAttestation",
398
+ "VerifiableAuthorisationToOnboard",
399
+ ];
400
+ break;
401
+ }
402
+ case "ti": {
403
+ requestedTypes = [
404
+ "VerifiableCredential",
405
+ "VerifiableAttestation",
406
+ "VerifiableAccreditation",
407
+ "VerifiableAccreditationToAttest",
408
+ ];
409
+ break;
410
+ }
411
+ case "tao": {
412
+ requestedTypes = [
413
+ "VerifiableCredential",
414
+ "VerifiableAttestation",
415
+ "VerifiableAccreditation",
416
+ "VerifiableAccreditationToAccredit",
417
+ ];
418
+ break;
419
+ }
420
+ case "roottao": {
421
+ requestedTypes = [
422
+ "VerifiableCredential",
423
+ "VerifiableAttestation",
424
+ "VerifiableAuthorisationForTrustChain",
425
+ ];
426
+ break;
427
+ }
428
+ case "ctrevocable": {
429
+ requestedTypes = [
430
+ "VerifiableCredential",
431
+ "VerifiableAttestation",
432
+ "CTRevocable",
433
+ ];
434
+ break;
435
+ }
436
+ case "qualification": {
437
+ requestedTypes = [
438
+ "VerifiableCredential",
439
+ "VerifiableAttestation",
440
+ "CTAAQualificationCredential",
441
+ ];
442
+ break;
443
+ }
444
+ default:
445
+ throw new Error(`type ${type} is not supported`);
446
+ }
447
+ // conformance clientMockInitiate
448
+ console.log("==> conformance clientMockInitiate");
449
+ await clientMockInitiate(context);
450
+ // opIssuer: conformance get /issuer-mock/.well-known/openid-credential-issuer
451
+ console.log(`==> conformance get ${openIdCredentialIssuerUrl}`);
452
+ const opIssuer = (await conformanceGet([openIdCredentialIssuerUrl], context));
453
+ const authorizationServer = opIssuer.authorization_server ?? opIssuer.credential_issuer;
454
+ // opConf: conformance get opIssuer.authorization_server /.well-known/openid-configuration
455
+ console.log(`==> conformance get ${authorizationServer}/.well-known/openid-configuration`);
456
+ const opConf = (await conformanceGet([authorizationServer, "/.well-known/openid-configuration"], context));
457
+ // respAuthorize: conformance authMockAuthorize opIssuer opConf requestedTypes ES256
458
+ console.log(`==> conformance authMockAuthorize ${stringify(opIssuer, [
459
+ "authorization_server",
460
+ "credential_issuer",
461
+ ])} ${stringify(opConf, ["authorization_endpoint"])} ${JSON.stringify(requestedTypes)} ${alg}`);
462
+ const respAuthorize = await authMockAuthorize([opIssuer, opConf, requestedTypes, alg], context);
463
+ let code;
464
+ if (type === "roottao") {
465
+ // vpJwt: compute createPresentationJwt vc alg opConf.issuer
466
+ console.log(`==> compute createPresentationJwt ${vc || "empty"} ${alg} ${opConf.issuer}`);
467
+ const vpJwt = (await compute("createPresentationJwt", [vc || "empty", alg, opConf.issuer], context));
468
+ // respDirectPost: conformance authMockDirectPostVpToken opIssuer opConf respAuthorize ES256
469
+ console.log(`==> conformance authMockDirectPostVpToken ${stringify(opConf, [
470
+ "redirect_uris",
471
+ ])} ${JSON.stringify(respAuthorize)} ${vpJwt}`);
472
+ const respDirectPost = (await authMockDirectPostVpToken([
473
+ opConf,
474
+ respAuthorize,
475
+ vpJwt,
476
+ ]));
477
+ code = respDirectPost.code;
478
+ }
479
+ else {
480
+ // respDirectPost: conformance authMockDirectPostIdToken opIssuer opConf respAuthorize ES256
481
+ console.log(`==> conformance authMockDirectPostIdToken ${stringify(opIssuer, [
482
+ "authorization_server",
483
+ "credential_issuer",
484
+ ])} ${stringify(opConf, ["redirect_uris"])} ${JSON.stringify(respAuthorize)} ${alg}`);
485
+ const respDirectPost = (await authMockDirectPostIdToken([opIssuer, opConf, respAuthorize, alg], context));
486
+ code = respDirectPost.code;
487
+ }
488
+ // resToken: conformance authMockToken opIssuer opConf respDirectPost.code ES256
489
+ console.log(`==> conformance authMockToken ${stringify(opIssuer, [
490
+ "authorization_server",
491
+ "credential_issuer",
492
+ ])} ${stringify(opConf, ["token_endpoint"])} ${code} ${alg}`);
493
+ const respToken = (await authMockToken([opIssuer, opConf, code, alg], context));
494
+ // using token resToken.access_token
495
+ console.log(`==> using token ${respToken.access_token}`);
496
+ context.httpOpts = {
497
+ headers: {
498
+ authorization: `Bearer ${respToken.access_token}`,
499
+ },
500
+ };
501
+ // resCredential: conformance issuerMockCredential opIssuer resToken.c_nonce requestedTypes ES256
502
+ console.log(`==> conformance issuerMockCredential ${stringify(opIssuer, [
503
+ "credential_issuer",
504
+ ])} ${respToken.c_nonce} ${JSON.stringify(requestedTypes)} ${alg}`);
505
+ const respCredential = (await issuerMockCredential([opIssuer, respToken.c_nonce, requestedTypes, alg], context));
506
+ let credential;
507
+ if (type === "roottao") {
508
+ console.log(`waiting 5.5 seconds...`);
509
+ await new Promise((r) => {
510
+ setTimeout(r, 5500);
511
+ });
512
+ // respDeferred: conformance issuerMockDeferred respDirectPost.acceptance_token
513
+ console.log(`==> conformance issuerMockDeferred ${stringify(opIssuer, [
514
+ "deferred_credential_endpoint",
515
+ ])} ${respCredential.acceptance_token}`);
516
+ const respDeferred = (await issuerMockDeferred([
517
+ opIssuer,
518
+ respCredential.acceptance_token,
519
+ ]));
520
+ credential = respDeferred.credential;
521
+ }
522
+ else {
523
+ credential = respCredential.credential;
524
+ }
525
+ // decodedCredential: compute decodeJWT resCredential.credential
526
+ console.log(`==> compute decodeJWT ${credential}`);
527
+ const decodedCredential = (await compute("decodeJWT", [credential], context));
528
+ let reservedAttributeId = "";
529
+ if (decodedCredential.payload.vc &&
530
+ decodedCredential.payload.vc.credentialSubject &&
531
+ decodedCredential.payload.vc.credentialSubject.reservedAttributeId) {
532
+ reservedAttributeId =
533
+ decodedCredential.payload.vc.credentialSubject.reservedAttributeId;
534
+ }
535
+ return {
536
+ vc: credential,
537
+ reservedAttributeId,
538
+ };
539
+ }
540
+ async function holder(inputs, context) {
541
+ const apiUrl = context.config.api.conformance.url;
542
+ const [credentialType, communicationType, inputAlg, vc, typeCredentialOffer, inputIssuer,] = inputs;
543
+ const alg = inputAlg || "ES256";
544
+ const codeVerifier = randomBytes(50).toString("base64url");
545
+ const requestedTypes = [
546
+ "VerifiableCredential",
547
+ "VerifiableAttestation",
548
+ credentialType,
549
+ ];
550
+ const openIdCredentialIssuerUrl = inputIssuer
551
+ ? `/client-mock/${inputIssuer}/.well-known/openid-credential-issuer`
552
+ : "/issuer-mock/.well-known/openid-credential-issuer";
553
+ const initiateCredentialOfferEndpoint = inputIssuer
554
+ ? `${apiUrl}/client-mock/${inputIssuer}/initiate-credential-offer`
555
+ : `${apiUrl}/issuer-mock/initiate-credential-offer`;
556
+ // credentialOffer: conformance issuerMockInitiateCredentialOffer initiateCredentialOfferEndpoint
557
+ console.log(`==> conformance issuerMockInitiateCredentialOffer ${initiateCredentialOfferEndpoint} ${credentialType}`);
558
+ let credentialOffer;
559
+ const validTypesIssuerState = [
560
+ "use-credential-offer",
561
+ "skip-credential-offer",
562
+ ];
563
+ if (typeCredentialOffer &&
564
+ !validTypesIssuerState.includes(typeCredentialOffer)) {
565
+ throw new Error(`invalid command for typeCredentialOffer. valid types: ${validTypesIssuerState.join(", ")}`);
566
+ }
567
+ const useCredentialOffer = typeCredentialOffer !== "skip-credential-offer";
568
+ const isPreauthorised = communicationType === "preAuthorised";
569
+ if (!useCredentialOffer) {
570
+ if (isPreauthorised)
571
+ throw new Error("For preauthorised credentials set use-credential-offer");
572
+ }
573
+ else {
574
+ credentialOffer = await issuerMockInitiateCredentialOffer([initiateCredentialOfferEndpoint, credentialType], context);
575
+ }
576
+ // opIssuer: conformance get /issuer-mock/.well-known/openid-credential-issuer
577
+ console.log(`==> conformance get ${openIdCredentialIssuerUrl}`);
578
+ const opIssuer = (await conformanceGet([openIdCredentialIssuerUrl], context));
579
+ const authorizationServer = opIssuer.authorization_server ?? opIssuer.credential_issuer;
580
+ // opConf: conformance get opIssuer.authorization_server /.well-known/openid-configuration
581
+ console.log(`==> conformance get ${authorizationServer}/.well-known/openid-configuration`);
582
+ const opConf = (await conformanceGet([authorizationServer, "/.well-known/openid-configuration"], context));
583
+ let code;
584
+ if (isPreauthorised) {
585
+ code =
586
+ credentialOffer.grants["urn:ietf:params:oauth:grant-type:pre-authorized_code"]?.["pre-authorized_code"];
587
+ }
588
+ else {
589
+ // respAuthorize: conformance authMockAuthorize opIssuer opConf requestedTypes ES256
590
+ let issuerState = "";
591
+ if (useCredentialOffer)
592
+ issuerState = credentialOffer.grants.authorization_code
593
+ ? credentialOffer.grants.authorization_code.issuer_state
594
+ : "";
595
+ console.log(`==> conformance authMockAuthorize ${stringify(opIssuer, [
596
+ "authorization_server",
597
+ "credential_issuer",
598
+ ])} ${stringify(opConf, ["authorization_endpoint"])} ${JSON.stringify(requestedTypes)} ${alg} ${codeVerifier} ${issuerState}`);
599
+ const respAuthorize = await authMockAuthorize([opIssuer, opConf, requestedTypes, alg, codeVerifier, issuerState], context);
600
+ if (credentialType === "CTWalletQualificationCredential") {
601
+ // vpJwt: compute createPresentationJwt vc alg opConf.issuer
602
+ console.log(`==> compute createPresentationJwt ${vc || "empty"} ${alg} ${opConf.issuer}`);
603
+ const vpJwt = (await compute("createPresentationJwt", [vc || "empty", alg, opConf.issuer], context));
604
+ // respDirectPost: conformance authMockDirectPostVpToken opIssuer opConf respAuthorize ES256
605
+ console.log(`==> conformance authMockDirectPostVpToken ${stringify(opConf, [
606
+ "redirect_uris",
607
+ ])} ${JSON.stringify(respAuthorize)} ${vpJwt} holder`);
608
+ const respDirectPost = (await authMockDirectPostVpToken([
609
+ opConf,
610
+ respAuthorize,
611
+ vpJwt,
612
+ "holder",
613
+ ]));
614
+ code = respDirectPost.code;
615
+ }
616
+ else {
617
+ // respDirectPost: conformance authMockDirectPostIdToken opIssuer opConf respAuthorize ES256
618
+ console.log(`==> conformance authMockDirectPostIdToken ${stringify(opIssuer, [
619
+ "authorization_server",
620
+ "credential_issuer",
621
+ ])} ${stringify(opConf, ["redirect_uris"])} ${JSON.stringify(respAuthorize)} ${alg}`);
622
+ const respDirectPost = (await authMockDirectPostIdToken([opIssuer, opConf, respAuthorize, alg], context));
623
+ code = respDirectPost.code;
624
+ }
625
+ }
626
+ // resToken: conformance authMockToken opIssuer opConf respDirectPost.code ES256
627
+ console.log(`==> conformance authMockToken ${stringify(opIssuer, [
628
+ "authorization_server",
629
+ "credential_issuer",
630
+ ])} ${stringify(opConf, ["token_endpoint"])} ${code} ${alg} ${codeVerifier}`);
631
+ const respToken = (await authMockToken([
632
+ opIssuer,
633
+ opConf,
634
+ code,
635
+ alg,
636
+ codeVerifier,
637
+ isPreauthorised ? "preAuthorised" : "",
638
+ ], context));
639
+ // using token resToken.access_token
640
+ console.log(`==> using token ${respToken.access_token}`);
641
+ context.httpOpts = {
642
+ headers: {
643
+ authorization: `Bearer ${respToken.access_token}`,
644
+ },
645
+ };
646
+ // resCredential: conformance issuerMockCredential opIssuer resToken.c_nonce requestedTypes ES256
647
+ console.log(`==> conformance issuerMockCredential ${stringify(opIssuer, [
648
+ "credential_issuer",
649
+ ])} ${respToken.c_nonce} ${JSON.stringify(requestedTypes)} ${alg}`);
650
+ const respCredential = (await issuerMockCredential([opIssuer, respToken.c_nonce, requestedTypes, alg], context));
651
+ let credential;
652
+ const isDeferred = communicationType === "deferred";
653
+ if (isDeferred) {
654
+ console.log(`waiting 5.5 seconds...`);
655
+ await new Promise((r) => {
656
+ setTimeout(r, 5500);
657
+ });
658
+ // respDeferred: conformance issuerMockDeferred respDirectPost.acceptance_token
659
+ console.log(`==> conformance issuerMockDeferred ${stringify(opIssuer, [
660
+ "deferred_credential_endpoint",
661
+ ])} ${respCredential.acceptance_token}`);
662
+ const respDeferred = (await issuerMockDeferred([
663
+ opIssuer,
664
+ respCredential.acceptance_token,
665
+ ]));
666
+ credential = respDeferred.credential;
667
+ }
668
+ else {
669
+ credential = respCredential.credential;
670
+ }
671
+ return credential;
672
+ }
673
+ async function check(inputs, context) {
674
+ const [intent, preAuthorizedCode, userPin] = inputs;
675
+ const apiUrl = context.config.api.conformance.url;
676
+ const response = await httpCall.post(`${apiUrl}/check`, {
677
+ data: {
678
+ clientId: context.client.clientId,
679
+ did: context.client.did,
680
+ credentialIssuer: context.client.clientId,
681
+ credentialIssuerDid: context.client.did,
682
+ issuerState: context.client.issuerState,
683
+ ...(preAuthorizedCode && {
684
+ preAuthorizedCode,
685
+ userPin,
686
+ }),
687
+ },
688
+ intent,
689
+ });
690
+ if (!response.data.success) {
691
+ red(response.data.errors);
692
+ throw new Error(`check ${intent} failed: ${response.data.errors
693
+ ? JSON.stringify(response.data.errors)
694
+ : "unknown error"}`);
695
+ }
696
+ return response.data;
697
+ }
698
+ export async function conformanceV3(method, inputs, context) {
699
+ switch (method) {
700
+ case "get": {
701
+ return conformanceGet(inputs, context);
702
+ }
703
+ case "clientMockInitiate": {
704
+ return clientMockInitiate(context);
705
+ }
706
+ case "clientMockUpdateList": {
707
+ return clientMockUpdateList(inputs, context);
708
+ }
709
+ case "authMockAuthorize": {
710
+ return authMockAuthorize(inputs, context);
711
+ }
712
+ case "authMockDirectPostIdToken": {
713
+ return authMockDirectPostIdToken(inputs, context);
714
+ }
715
+ case "authMockDirectPostVpToken": {
716
+ return authMockDirectPostVpToken(inputs);
717
+ }
718
+ case "authMockToken": {
719
+ return authMockToken(inputs, context);
720
+ }
721
+ case "issuerMockCredential": {
722
+ return issuerMockCredential(inputs, context);
723
+ }
724
+ case "issuerMockDeferred": {
725
+ return issuerMockDeferred(inputs);
726
+ }
727
+ case "issuerMockInitiateCredentialOffer": {
728
+ return issuerMockInitiateCredentialOffer(inputs, context);
729
+ }
730
+ case "getCredential": {
731
+ return getCredential(inputs, context);
732
+ }
733
+ case "holder": {
734
+ return holder(inputs, context);
735
+ }
736
+ case "check": {
737
+ return check(inputs, context);
738
+ }
739
+ default:
740
+ red(`Invalid method '${method}'`);
741
+ return 0;
742
+ }
743
+ }
744
+ export default conformanceV3;
745
+ //# sourceMappingURL=conformance-v3.js.map