@verii/server-credentialing-hub 2.0.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 (237) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +13 -0
  3. package/package.json +87 -0
  4. package/src/assets/templates/app-redirect.hbs +22 -0
  5. package/src/config/config.js +118 -0
  6. package/src/config/index.js +19 -0
  7. package/src/controllers/app-redirect/controller.js +85 -0
  8. package/src/controllers/openid4vc/autohooks.js +22 -0
  9. package/src/controllers/openid4vc/oauth-controller.js +96 -0
  10. package/src/controllers/openid4vc/openid4vc-metadata-controller.js +66 -0
  11. package/src/controllers/openid4vc/openid4vci-controller.js +125 -0
  12. package/src/controllers/openid4vp/autohooks.js +22 -0
  13. package/src/controllers/openid4vp/openid4vp-controller.js +177 -0
  14. package/src/controllers/operator/autohooks.js +31 -0
  15. package/src/controllers/operator/credentials/credentials-controller.js +212 -0
  16. package/src/controllers/operator/credentials/schemas/credential.schema.js +46 -0
  17. package/src/controllers/operator/credentials/schemas/index.js +7 -0
  18. package/src/controllers/operator/credentials/schemas/new-credential.schema.json +23 -0
  19. package/src/controllers/operator/depots/depots-controller.js +154 -0
  20. package/src/controllers/operator/depots/schemas/depot.schema.js +34 -0
  21. package/src/controllers/operator/depots/schemas/index.js +24 -0
  22. package/src/controllers/operator/depots/schemas/new-depot.schema.json +30 -0
  23. package/src/controllers/operator/issue-links/issue-links-controller.js +74 -0
  24. package/src/controllers/operator/issuer-services/issuer-services-controller.js +200 -0
  25. package/src/controllers/operator/issuer-services/schemas/index.js +7 -0
  26. package/src/controllers/operator/issuer-services/schemas/issuer-service.schema.js +26 -0
  27. package/src/controllers/operator/issuer-services/schemas/new-issuer-service.schema.js +137 -0
  28. package/src/controllers/operator/presentation-links/presentation-links-controller.js +76 -0
  29. package/src/controllers/operator/presentations/presentations-controller.js +174 -0
  30. package/src/controllers/operator/presentations/schemas/base-presentation.schema.js +39 -0
  31. package/src/controllers/operator/presentations/schemas/credential-verification.schema.js +83 -0
  32. package/src/controllers/operator/presentations/schemas/index.js +23 -0
  33. package/src/controllers/operator/presentations/schemas/presentation-verification.schema.js +42 -0
  34. package/src/controllers/operator/presentations/schemas/presentation.schema.js +53 -0
  35. package/src/controllers/operator/presentations/schemas/w3c-presentation.js +52 -0
  36. package/src/controllers/operator/relying-party-services/relying-party-services-controller.js +202 -0
  37. package/src/controllers/operator/relying-party-services/schemas/index.js +7 -0
  38. package/src/controllers/operator/relying-party-services/schemas/new-relying-party-service.schema.js +91 -0
  39. package/src/controllers/operator/relying-party-services/schemas/relying-party-service.schema.js +26 -0
  40. package/src/controllers/operator/tenants/schemas/index.js +33 -0
  41. package/src/controllers/operator/tenants/schemas/jwk.schema.json +56 -0
  42. package/src/controllers/operator/tenants/schemas/key-metadata.schema.json +12 -0
  43. package/src/controllers/operator/tenants/schemas/new-key-metadata.schema.json +42 -0
  44. package/src/controllers/operator/tenants/schemas/new-key.schema.json +12 -0
  45. package/src/controllers/operator/tenants/schemas/new-tenant.schema.json +33 -0
  46. package/src/controllers/operator/tenants/schemas/secret-key.schema.json +33 -0
  47. package/src/controllers/operator/tenants/schemas/tenant.schema.json +44 -0
  48. package/src/controllers/operator/tenants/tenants-controller.js +165 -0
  49. package/src/controllers/root-controller.js +43 -0
  50. package/src/controllers/vn-api/schemas/index.js +25 -0
  51. package/src/controllers/vn-api/schemas/presentation-submission.schema.json +41 -0
  52. package/src/controllers/vn-api/schemas/velocity-presentation-submission.response.200.schema.json +36 -0
  53. package/src/controllers/vn-api/schemas/velocity-presentation-submission.schema.json +31 -0
  54. package/src/controllers/vn-api/vn-api-presentation-controller.js +158 -0
  55. package/src/controllers/vn-api/vn-issuing-controller.js +295 -0
  56. package/src/entities/credential-types/fetchers/fetch-credential-type-descriptors.js +36 -0
  57. package/src/entities/credential-types/fetchers/index.js +19 -0
  58. package/src/entities/credential-types/index.js +19 -0
  59. package/src/entities/credentials/domain/canonicalize-credentials.js +70 -0
  60. package/src/entities/credentials/domain/credential-errors.js +25 -0
  61. package/src/entities/credentials/domain/credential-format.js +21 -0
  62. package/src/entities/credentials/domain/index.js +22 -0
  63. package/src/entities/credentials/domain/validate-credential.js +74 -0
  64. package/src/entities/credentials/facades/anchor-verii-credentials-facade.js +45 -0
  65. package/src/entities/credentials/facades/build-verii-issuer.js +44 -0
  66. package/src/entities/credentials/facades/index.js +22 -0
  67. package/src/entities/credentials/facades/issue-verii-credentials-facade.js +62 -0
  68. package/src/entities/credentials/facades/sign-verii-credentials-facade.js +56 -0
  69. package/src/entities/credentials/factories/credential-factory.js +53 -0
  70. package/src/entities/credentials/factories/index.js +19 -0
  71. package/src/entities/credentials/index.js +23 -0
  72. package/src/entities/credentials/orchestrators/create-credentials.js +118 -0
  73. package/src/entities/credentials/orchestrators/index.js +19 -0
  74. package/src/entities/credentials/repo/finders-extension.js +94 -0
  75. package/src/entities/credentials/repo/index.js +19 -0
  76. package/src/entities/credentials/repo/repo.js +62 -0
  77. package/src/entities/credentials/repo/update-issued-credential.js +60 -0
  78. package/src/entities/depots/domain/depot-errors.js +23 -0
  79. package/src/entities/depots/domain/index.js +20 -0
  80. package/src/entities/depots/domain/validate-depot.js +38 -0
  81. package/src/entities/depots/factories/depot-factory.js +50 -0
  82. package/src/entities/depots/factories/index.js +19 -0
  83. package/src/entities/depots/index.js +22 -0
  84. package/src/entities/depots/orchestrators/create-depot.js +31 -0
  85. package/src/entities/depots/orchestrators/delete-depot.js +43 -0
  86. package/src/entities/depots/orchestrators/index.js +20 -0
  87. package/src/entities/depots/repo/find-depot-by-preauth-code.js +30 -0
  88. package/src/entities/depots/repo/find-depots-extension.js +34 -0
  89. package/src/entities/depots/repo/index.js +19 -0
  90. package/src/entities/depots/repo/refresh-preauth-code.js +30 -0
  91. package/src/entities/depots/repo/repo.js +61 -0
  92. package/src/entities/exchanges/adapters/index.js +17 -0
  93. package/src/entities/exchanges/adapters/sign-exchange-response.js +37 -0
  94. package/src/entities/exchanges/domain/authorize-exchange.js +29 -0
  95. package/src/entities/exchanges/domain/build-exchange-event.js +19 -0
  96. package/src/entities/exchanges/domain/build-presentation-request.js +174 -0
  97. package/src/entities/exchanges/domain/exchange-errors.js +28 -0
  98. package/src/entities/exchanges/domain/exchange-protocols.js +29 -0
  99. package/src/entities/exchanges/domain/exchange-states.js +53 -0
  100. package/src/entities/exchanges/domain/exchange-types.js +22 -0
  101. package/src/entities/exchanges/domain/generate-issuing-challenge.js +48 -0
  102. package/src/entities/exchanges/domain/index.js +32 -0
  103. package/src/entities/exchanges/domain/validate-message-settings.js +33 -0
  104. package/src/entities/exchanges/domain/validate-new-exchange.js +25 -0
  105. package/src/entities/exchanges/domain/validate-preauth.js +45 -0
  106. package/src/entities/exchanges/domain/validate-referenced-service.js +33 -0
  107. package/src/entities/exchanges/domain/verify-issuing-challenge.js +42 -0
  108. package/src/entities/exchanges/domain/verify-proof-of-key-possession.js +128 -0
  109. package/src/entities/exchanges/factories/index.js +19 -0
  110. package/src/entities/exchanges/factories/init-exchange-factory.js +58 -0
  111. package/src/entities/exchanges/hooks/exchange-error-hook.js +30 -0
  112. package/src/entities/exchanges/hooks/index.js +17 -0
  113. package/src/entities/exchanges/index.js +24 -0
  114. package/src/entities/exchanges/orchestrators/authenticate.js +67 -0
  115. package/src/entities/exchanges/orchestrators/credential-offer-request.js +70 -0
  116. package/src/entities/exchanges/orchestrators/get-credential-manifest.js +84 -0
  117. package/src/entities/exchanges/orchestrators/get-presentation-request.js +114 -0
  118. package/src/entities/exchanges/orchestrators/index.js +24 -0
  119. package/src/entities/exchanges/orchestrators/issue-credentials.js +132 -0
  120. package/src/entities/exchanges/orchestrators/post-presentation.js +58 -0
  121. package/src/entities/exchanges/repo/exchange-state-repo-extension.js +78 -0
  122. package/src/entities/exchanges/repo/index.js +19 -0
  123. package/src/entities/exchanges/repo/repo.js +52 -0
  124. package/src/entities/issuer-services/domain/index.js +20 -0
  125. package/src/entities/issuer-services/domain/issuer-services-errors.js +23 -0
  126. package/src/entities/issuer-services/domain/validate-issuer-service.js +23 -0
  127. package/src/entities/issuer-services/factories/index.js +19 -0
  128. package/src/entities/issuer-services/factories/issuer-service-factory.js +44 -0
  129. package/src/entities/issuer-services/index.js +21 -0
  130. package/src/entities/issuer-services/repo/find-issuer-services-extension.js +30 -0
  131. package/src/entities/issuer-services/repo/index.js +19 -0
  132. package/src/entities/issuer-services/repo/repo.js +59 -0
  133. package/src/entities/keys/adapters/index.js +19 -0
  134. package/src/entities/keys/adapters/load-primary-account.js +39 -0
  135. package/src/entities/keys/domain/cih-key-purposes.js +23 -0
  136. package/src/entities/keys/domain/get-key-with-purpose.js +22 -0
  137. package/src/entities/keys/domain/index.js +22 -0
  138. package/src/entities/keys/domain/key-errors.js +25 -0
  139. package/src/entities/keys/domain/normalize-tenant-key.js +33 -0
  140. package/src/entities/keys/domain/validate-tenant-keys.js +78 -0
  141. package/src/entities/keys/factories/index.js +19 -0
  142. package/src/entities/keys/factories/key-factory.js +61 -0
  143. package/src/entities/keys/index.js +22 -0
  144. package/src/entities/keys/plugins/index.js +17 -0
  145. package/src/entities/keys/plugins/kms-plugin.js +61 -0
  146. package/src/entities/links/domain/build-deep-link-url.js +58 -0
  147. package/src/entities/links/domain/build-openid4vci-credential-offer-link.js +31 -0
  148. package/src/entities/links/domain/build-openid4vp-authorization-request-link.js +36 -0
  149. package/src/entities/links/domain/build-redirect-url.js +29 -0
  150. package/src/entities/links/domain/build-vn-api-issuing-link.js +54 -0
  151. package/src/entities/links/domain/build-vn-api-presentation-link.js +49 -0
  152. package/src/entities/links/domain/index.js +28 -0
  153. package/src/entities/links/domain/is-preauth-code-auth.js +19 -0
  154. package/src/entities/links/domain/link-errors.js +23 -0
  155. package/src/entities/links/domain/validate-issue-link.js +39 -0
  156. package/src/entities/links/domain/validate-presentation-link.js +39 -0
  157. package/src/entities/links/index.js +20 -0
  158. package/src/entities/links/orchestrators/index.js +17 -0
  159. package/src/entities/links/orchestrators/refresh-links.js +139 -0
  160. package/src/entities/openid4vci/domain/index.js +20 -0
  161. package/src/entities/openid4vci/domain/openid4vci-errors.js +24 -0
  162. package/src/entities/openid4vci/domain/to-credential-configuration-id.js +21 -0
  163. package/src/entities/openid4vci/index.js +21 -0
  164. package/src/entities/openid4vci/orchestrators/create-access-token.js +85 -0
  165. package/src/entities/openid4vci/orchestrators/create-credential.js +108 -0
  166. package/src/entities/openid4vci/orchestrators/get-authorization-server-metadata.js +22 -0
  167. package/src/entities/openid4vci/orchestrators/get-credential-issuer-metadata.js +22 -0
  168. package/src/entities/openid4vci/orchestrators/handle-notification.js +94 -0
  169. package/src/entities/openid4vci/orchestrators/index.js +24 -0
  170. package/src/entities/openid4vci/plugins/index.js +19 -0
  171. package/src/entities/openid4vci/plugins/openid4vci-plugin.js +427 -0
  172. package/src/entities/openid4vp/domain/index.js +21 -0
  173. package/src/entities/openid4vp/domain/openid4vp-request-id.js +47 -0
  174. package/src/entities/openid4vp/domain/presentation-request-expiry.js +37 -0
  175. package/src/entities/openid4vp/domain/wallet-metadata.js +30 -0
  176. package/src/entities/openid4vp/index.js +21 -0
  177. package/src/entities/openid4vp/orchestrators/create-authorization-request.js +183 -0
  178. package/src/entities/openid4vp/orchestrators/index.js +20 -0
  179. package/src/entities/openid4vp/orchestrators/post-authorization-response.js +353 -0
  180. package/src/entities/openid4vp/plugins/index.js +19 -0
  181. package/src/entities/openid4vp/plugins/openid4vp-plugin.js +174 -0
  182. package/src/entities/presentations/domain/index.js +20 -0
  183. package/src/entities/presentations/domain/presentation-format.js +20 -0
  184. package/src/entities/presentations/domain/validate-presentation.js +178 -0
  185. package/src/entities/presentations/factories/index.js +19 -0
  186. package/src/entities/presentations/factories/presentation-factory.js +96 -0
  187. package/src/entities/presentations/index.js +21 -0
  188. package/src/entities/presentations/orchestrators/index.js +19 -0
  189. package/src/entities/presentations/orchestrators/verify-presentation.js +131 -0
  190. package/src/entities/presentations/repo/add-verification.js +31 -0
  191. package/src/entities/presentations/repo/finders-extension.js +50 -0
  192. package/src/entities/presentations/repo/index.js +19 -0
  193. package/src/entities/presentations/repo/repo.js +58 -0
  194. package/src/entities/relying-party-services/factories/index.js +19 -0
  195. package/src/entities/relying-party-services/factories/relying-party-service-factory.js +43 -0
  196. package/src/entities/relying-party-services/index.js +20 -0
  197. package/src/entities/relying-party-services/repo/find-relying-party-services-extension.js +30 -0
  198. package/src/entities/relying-party-services/repo/index.js +19 -0
  199. package/src/entities/relying-party-services/repo/repo.js +55 -0
  200. package/src/entities/service-configurations/domain/canonicalize-service-configuration.js +12 -0
  201. package/src/entities/service-configurations/domain/index.js +22 -0
  202. package/src/entities/service-configurations/domain/service-configuration-errors.js +24 -0
  203. package/src/entities/service-configurations/domain/validate-service-configuration.js +31 -0
  204. package/src/entities/service-configurations/domain/validate-update-service-configuration.js +19 -0
  205. package/src/entities/service-configurations/index.js +20 -0
  206. package/src/entities/service-configurations/orchestrators/create-service-configuration.js +34 -0
  207. package/src/entities/service-configurations/orchestrators/delete-service-configuration.js +41 -0
  208. package/src/entities/service-configurations/orchestrators/index.js +21 -0
  209. package/src/entities/service-configurations/orchestrators/update-service-configuration.js +40 -0
  210. package/src/entities/tenants/adapters/index.js +20 -0
  211. package/src/entities/tenants/adapters/load-tenant-did-doc.js +47 -0
  212. package/src/entities/tenants/adapters/load-tenant-profile.js +40 -0
  213. package/src/entities/tenants/domain/index.js +20 -0
  214. package/src/entities/tenants/domain/tenant-errors.js +29 -0
  215. package/src/entities/tenants/domain/validate-new-tenant.js +49 -0
  216. package/src/entities/tenants/factories/index.js +19 -0
  217. package/src/entities/tenants/factories/tenant-factory.js +41 -0
  218. package/src/entities/tenants/index.js +24 -0
  219. package/src/entities/tenants/orchestrators/create-tenant.js +116 -0
  220. package/src/entities/tenants/orchestrators/delete-tenant.js +45 -0
  221. package/src/entities/tenants/orchestrators/find-tenants.js +22 -0
  222. package/src/entities/tenants/orchestrators/index.js +21 -0
  223. package/src/entities/tenants/plugins/index.js +3 -0
  224. package/src/entities/tenants/plugins/tenant-loader-plugin.js +64 -0
  225. package/src/entities/tenants/repo/index.js +19 -0
  226. package/src/entities/tenants/repo/insert-tenant-extension.js +36 -0
  227. package/src/entities/tenants/repo/repo.js +51 -0
  228. package/src/entities/tokens/domains/access-token.js +74 -0
  229. package/src/entities/tokens/domains/index.js +19 -0
  230. package/src/entities/tokens/index.js +19 -0
  231. package/src/index.js +3 -0
  232. package/src/init-server.js +88 -0
  233. package/src/main.js +25 -0
  234. package/src/schemas/index.js +20 -0
  235. package/src/schemas/oauth-error-response.schema.js +27 -0
  236. package/src/standalone.js +8 -0
  237. package/src/start-app-server.js +27 -0
@@ -0,0 +1,61 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const fp = require('fastify-plugin');
19
+ const { dbKmsPlugin } = require('@verii/db-kms');
20
+ const { multitenantExtension } = require('@verii/spencer-mongo-extensions');
21
+
22
+ const kmsRepoOptions = {
23
+ name: 'keys',
24
+ entityName: 'key',
25
+ keyProp: 'jwk',
26
+ encryptedKeyProp: 'encryptedJwk',
27
+ publicKeyProp: 'publicJwk',
28
+ symmetricEncryptionKey: 'keyEncryptionSecret',
29
+ defaultProjection: {
30
+ _id: 1,
31
+ purposes: 1,
32
+ algorithm: 1,
33
+ encoding: 1,
34
+ kidFragment: 1,
35
+ publicJwk: 1,
36
+ tenantId: 1,
37
+ createdAt: 1,
38
+ updatedAt: 1,
39
+ },
40
+ extensions: [multitenantExtension()],
41
+ };
42
+
43
+ const kmsPlugin = async (fastify) => {
44
+ fastify.register(dbKmsPlugin, {
45
+ ...kmsRepoOptions,
46
+ transformToKmsKey: (result) => {
47
+ /* eslint-disable better-mutation/no-mutation */
48
+ result.id = result._id.toString();
49
+ result._id = undefined;
50
+
51
+ result.privateJwk = result.jwk;
52
+ result.jwk = undefined;
53
+ /* eslint-enable */
54
+ return result;
55
+ },
56
+ });
57
+ };
58
+ module.exports = {
59
+ kmsPlugin: fp(kmsPlugin, { name: 'kms-plugin' }),
60
+ kmsRepoOptions,
61
+ };
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { flow, zip, range, map, forEach, castArray } = require('lodash/fp');
18
+ const { appendSearchParam } = require('@verii/common-functions');
19
+
20
+ const buildDeepLinkUrl = (
21
+ requestUri,
22
+ inspectorDid,
23
+ issuerDid,
24
+ vendorOriginContext,
25
+ suffix,
26
+ deepLinkProtocol,
27
+ ) => {
28
+ const requestUris = castArray(requestUri);
29
+ const inspectorDids = castArray(inspectorDid);
30
+ const issuerDids = castArray(issuerDid);
31
+ const vendorOriginContexts = castArray(vendorOriginContext);
32
+ const parsedLinks = flow(
33
+ (items) => zip(items, range(0, items.length)),
34
+ map(([value, index]) => ({
35
+ _requestUri: value,
36
+ _vendorOriginContext: vendorOriginContexts[index],
37
+ _inspectorDid: inspectorDids[index],
38
+ _issuerDid: issuerDids[index],
39
+ })),
40
+ )(requestUris);
41
+ const url = new URL(`${deepLinkProtocol}${suffix}`);
42
+ forEach(
43
+ ({ _requestUri, _inspectorDid, _issuerDid, _vendorOriginContext }) => {
44
+ flow(
45
+ appendSearchParam('request_uri', _requestUri),
46
+ appendSearchParam('inspectorDid', _inspectorDid),
47
+ appendSearchParam('issuerDid', _issuerDid),
48
+ appendSearchParam('vendorOriginContext', _vendorOriginContext),
49
+ )(url);
50
+ },
51
+ parsedLinks,
52
+ );
53
+ return url;
54
+ };
55
+
56
+ module.exports = {
57
+ buildDeepLinkUrl,
58
+ };
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const buildCredentialOfferLink = async (depot, credentialTypes, context) => {
19
+ if (depot?.preauthCode == null) {
20
+ context.log.info(
21
+ 'auth flow not supported, skipping openid4vc credential-offer uri generation',
22
+ );
23
+ return undefined;
24
+ }
25
+ const { createCredentialOffer } = await context.getOpenId4VciIssuer();
26
+ return createCredentialOffer(credentialTypes, depot.preauthCode);
27
+ };
28
+
29
+ module.exports = {
30
+ buildCredentialOfferLink,
31
+ };
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright 2026 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const buildOpenid4vpAuthorizationRequestLink = (tenant, requestId) => {
19
+ const requestUri = buildOpenid4vpAuthorizationRequestUri(tenant, requestId);
20
+ const protocolLinkUrl = new URL('openid4vp://authorize');
21
+ protocolLinkUrl.searchParams.append(
22
+ 'client_id',
23
+ `decentralized_identifier:${tenant.did}`,
24
+ );
25
+ protocolLinkUrl.searchParams.append('request_uri', requestUri);
26
+ protocolLinkUrl.searchParams.append('request_uri_method', 'post');
27
+ return { protocolLink: protocolLinkUrl.href, requestUri };
28
+ };
29
+
30
+ const buildOpenid4vpAuthorizationRequestUri = (tenant, requestId) =>
31
+ `${tenant.hostUrl}/r/${tenant._id}/openid4vp/authorization-request/${requestId}`;
32
+
33
+ module.exports = {
34
+ buildOpenid4vpAuthorizationRequestLink,
35
+ buildOpenid4vpAuthorizationRequestUri,
36
+ };
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const buildRedirectUrl = (tenant, vnProtocolLinkUrl, openid4vcProtocolUrl) => {
19
+ const redirectUrl = new URL(`${tenant.hostUrl}/app-redirect`);
20
+ redirectUrl.searchParams.append('deeplink', vnProtocolLinkUrl.href);
21
+
22
+ // if no depot.preauthCode, then for now we have a null openid4vcProtocolUrl value
23
+ if (openid4vcProtocolUrl != null) {
24
+ redirectUrl.searchParams.append('openid4vc_uri', openid4vcProtocolUrl);
25
+ }
26
+ return redirectUrl;
27
+ };
28
+
29
+ module.exports = { buildRedirectUrl };
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { flow } = require('lodash/fp');
19
+ const {
20
+ appendSearchParam,
21
+ appendSearchParamArray,
22
+ } = require('@verii/common-functions');
23
+ const { buildDeepLinkUrl } = require('./build-deep-link-url');
24
+
25
+ const buildIssuingDeepLink = (
26
+ tenant,
27
+ service,
28
+ depot,
29
+ credentialTypes,
30
+ deepLinkProtocol,
31
+ ) => {
32
+ const credentialManifestUrl = flow(
33
+ appendSearchParam('id', service._id.toString()),
34
+ appendSearchParamArray('credential_types', credentialTypes),
35
+ )(createPresentationRequestUrl('get-credential-manifest', tenant));
36
+
37
+ return buildDeepLinkUrl(
38
+ credentialManifestUrl,
39
+ null,
40
+ tenant.did,
41
+ depot?.preauthCode != null
42
+ ? `depot:${depot?._id}:${depot?.preauthCode}`
43
+ : undefined,
44
+ 'issue',
45
+ deepLinkProtocol,
46
+ );
47
+ };
48
+
49
+ const createPresentationRequestUrl = (suffix, tenant) =>
50
+ new URL(`${tenant.hostUrl}/vn-api/r/${encodeURI(tenant.did)}/${suffix}`);
51
+
52
+ module.exports = {
53
+ buildIssuingDeepLink,
54
+ };
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright 2026 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { appendSearchParam } = require('@verii/common-functions');
19
+ const { buildDeepLinkUrl } = require('./build-deep-link-url');
20
+
21
+ const buildPresentationDeepLink = (
22
+ tenant,
23
+ service,
24
+ depot,
25
+ deepLinkProtocol,
26
+ ) => {
27
+ const presentationRequestUrl = appendSearchParam(
28
+ 'id',
29
+ service._id,
30
+ )(createPresentationRequestUrl(tenant));
31
+
32
+ return buildDeepLinkUrl(
33
+ presentationRequestUrl,
34
+ tenant.did,
35
+ null,
36
+ depot?._id != null ? `depot:${depot._id}` : undefined,
37
+ 'inspect',
38
+ deepLinkProtocol,
39
+ );
40
+ };
41
+
42
+ const createPresentationRequestUrl = (tenant) =>
43
+ new URL(
44
+ `${tenant.hostUrl}/vn-api/r/${encodeURI(tenant.did)}/get-presentation-request`,
45
+ );
46
+
47
+ module.exports = {
48
+ buildPresentationDeepLink,
49
+ };
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ module.exports = {
18
+ ...require('./build-deep-link-url'),
19
+ ...require('./build-redirect-url'),
20
+ ...require('./build-vn-api-issuing-link'),
21
+ ...require('./build-vn-api-presentation-link'),
22
+ ...require('./build-openid4vci-credential-offer-link'),
23
+ ...require('./build-openid4vp-authorization-request-link'),
24
+ ...require('./is-preauth-code-auth'),
25
+ ...require('./link-errors'),
26
+ ...require('./validate-issue-link'),
27
+ ...require('./validate-presentation-link'),
28
+ };
@@ -0,0 +1,19 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const isPreauthCodeAuth = (service) => service.authMethods.includes('preauth');
18
+
19
+ module.exports = { isPreauthCodeAuth };
@@ -0,0 +1,23 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const LinkErrors = {
18
+ issue_link_requires_depotId: 'issue_link_requires_depotId',
19
+ referenced_service_not_found: 'referenced_service_not_found',
20
+ referenced_depot_not_found: 'referenced_depot_not_found',
21
+ };
22
+
23
+ module.exports = { LinkErrors };
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const newError = require('http-errors');
18
+ const { LinkErrors } = require('./link-errors');
19
+ const { isPreauthCodeAuth } = require('./is-preauth-code-auth');
20
+
21
+ const validateIssueLink = (service, depotId, depot) => {
22
+ if (service == null) {
23
+ throw newError(400, LinkErrors.referenced_service_not_found, {
24
+ errorCode: LinkErrors.referenced_service_not_found,
25
+ });
26
+ }
27
+ if (depotId != null && depot == null) {
28
+ throw newError(400, LinkErrors.referenced_depot_not_found, {
29
+ errorCode: LinkErrors.referenced_depot_not_found,
30
+ });
31
+ }
32
+ if (isPreauthCodeAuth(service) && depot == null) {
33
+ throw newError(400, LinkErrors.issue_link_requires_depotId, {
34
+ errorCode: LinkErrors.issue_link_requires_depotId,
35
+ });
36
+ }
37
+ };
38
+
39
+ module.exports = { validateIssueLink };
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright 2026 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const newError = require('http-errors');
19
+ const {
20
+ validateReferencedService,
21
+ } = require('../../exchanges/domain/validate-referenced-service');
22
+ const { LinkErrors } = require('./link-errors');
23
+
24
+ const validatePresentationLink = (service, serviceId, depotId, depot) => {
25
+ validateReferencedService(service);
26
+
27
+ if (depotId != null && !isMatchingDepot(depot, serviceId)) {
28
+ throw newError(400, LinkErrors.referenced_depot_not_found, {
29
+ errorCode: LinkErrors.referenced_depot_not_found,
30
+ });
31
+ }
32
+ };
33
+
34
+ const isMatchingDepot = (depot, serviceId) =>
35
+ depot != null && depot.serviceId?.toString() === serviceId.toString();
36
+
37
+ module.exports = {
38
+ validatePresentationLink,
39
+ };
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ module.exports = {
18
+ ...require('./domain'),
19
+ ...require('./orchestrators'),
20
+ };
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ module.exports = { ...require('./refresh-links') };
@@ -0,0 +1,139 @@
1
+ /*
2
+ * Copyright 2024 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { flatMap, flow, isEmpty, omit, uniq } = require('lodash/fp');
19
+ const { optional } = require('@verii/common-functions');
20
+ const {
21
+ OPENID4VP_DEPOT_REQUEST_PREFIX,
22
+ OPENID4VP_SERVICE_REQUEST_PREFIX,
23
+ } = require('../../openid4vp/domain/openid4vp-request-id');
24
+ const {
25
+ buildCredentialOfferLink,
26
+ buildIssuingDeepLink,
27
+ buildOpenid4vpAuthorizationRequestLink,
28
+ buildPresentationDeepLink,
29
+ buildRedirectUrl,
30
+ isPreauthCodeAuth,
31
+ validateIssueLink,
32
+ validatePresentationLink,
33
+ } = require('../domain');
34
+
35
+ // eslint-disable-next-line complexity
36
+ const refreshIssueLinks = async (serviceId, depotId, context) => {
37
+ const { config, repos, tenant } = context;
38
+ const [service, depot] = await Promise.all([
39
+ repos.issuerServices.findOne({ filter: { _id: serviceId } }),
40
+ repos.depots.findOne({ filter: { _id: depotId } }),
41
+ ]);
42
+ validateIssueLink(service, depotId, depot);
43
+
44
+ const refreshedDepot = isPreauthCodeAuth(service)
45
+ ? await repos.depots.refreshPreauthCode(depotId)
46
+ : depot;
47
+
48
+ // Credential types are extracted from the depot
49
+ const credentialTypes = await optional(loadCredentialTypeHints, [
50
+ refreshedDepot,
51
+ context,
52
+ ]);
53
+
54
+ const vnProtocolLinkUrl = buildIssuingDeepLink(
55
+ tenant,
56
+ service,
57
+ refreshedDepot,
58
+ credentialTypes,
59
+ config.deepLinkProtocol,
60
+ );
61
+
62
+ const openid4vciProtocolLinkUrl =
63
+ refreshedDepot?.preauthCode != null && !isEmpty(credentialTypes)
64
+ ? await buildCredentialOfferLink(refreshedDepot, credentialTypes, context)
65
+ : undefined;
66
+ const redirectUrl = buildRedirectUrl(
67
+ tenant,
68
+ vnProtocolLinkUrl,
69
+ openid4vciProtocolLinkUrl,
70
+ );
71
+
72
+ const links = {
73
+ redirectUrl: redirectUrl.href,
74
+ vnProtocolLink: vnProtocolLinkUrl.href,
75
+ openidCredentialOffer: openid4vciProtocolLinkUrl,
76
+ };
77
+
78
+ if (refreshedDepot?.preauthCode) {
79
+ links.preauthCode = refreshedDepot.preauthCode;
80
+ }
81
+ return links;
82
+ };
83
+
84
+ const loadCredentialTypeHints = async (depot, context) => {
85
+ const credentials = await context.repos.credentials.find(
86
+ { filter: { depotId: depot._id } },
87
+ { 'content.type': 1 },
88
+ );
89
+ return flow(
90
+ flatMap('content.type'),
91
+ uniq,
92
+ omit(['VerifiableCredential']),
93
+ )(credentials);
94
+ };
95
+
96
+ const refreshPresentationLinks = async (serviceId, depotId, context) => {
97
+ const { config, repos, tenant } = context;
98
+ const [service, depot] = await Promise.all([
99
+ repos.relyingPartyServices.findOne({ filter: { _id: serviceId } }),
100
+ optional(loadDepot, [depotId, repos]),
101
+ ]);
102
+ validatePresentationLink(service, serviceId, depotId, depot);
103
+
104
+ const vnProtocolLinkUrl = buildPresentationDeepLink(
105
+ tenant,
106
+ service,
107
+ depot,
108
+ config.deepLinkProtocol,
109
+ );
110
+ const openid4vpRequestId = buildOpenid4vpRequestId(serviceId, depotId);
111
+ const openid4vpLink = buildOpenid4vpAuthorizationRequestLink(
112
+ tenant,
113
+ openid4vpRequestId,
114
+ );
115
+ const redirectUrl = buildRedirectUrl(
116
+ tenant,
117
+ vnProtocolLinkUrl,
118
+ openid4vpLink.protocolLink,
119
+ );
120
+
121
+ return {
122
+ redirectUrl: redirectUrl.href,
123
+ vnProtocolLink: vnProtocolLinkUrl.href,
124
+ openid4vpProtocolLink: openid4vpLink.protocolLink,
125
+ };
126
+ };
127
+
128
+ const loadDepot = (depotId, repos) =>
129
+ repos.depots.findOne({ filter: { _id: depotId } });
130
+
131
+ const buildOpenid4vpRequestId = (serviceId, depotId) =>
132
+ depotId == null
133
+ ? `${OPENID4VP_SERVICE_REQUEST_PREFIX}${serviceId}`
134
+ : `${OPENID4VP_DEPOT_REQUEST_PREFIX}${depotId}`;
135
+
136
+ module.exports = {
137
+ refreshIssueLinks,
138
+ refreshPresentationLinks,
139
+ };
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ module.exports = {
18
+ ...require('./openid4vci-errors'),
19
+ ...require('./to-credential-configuration-id'),
20
+ };