@pagopa/io-react-native-wallet 0.7.4 → 0.9.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 (211) hide show
  1. package/README.md +49 -31
  2. package/lib/commonjs/credential/index.js +13 -0
  3. package/lib/commonjs/credential/index.js.map +1 -0
  4. package/lib/commonjs/credential/issuance/01-start-flow.js +2 -0
  5. package/lib/commonjs/credential/issuance/01-start-flow.js.map +1 -0
  6. package/lib/commonjs/credential/issuance/02-evaluate-issuer-trust.js +26 -0
  7. package/lib/commonjs/credential/issuance/02-evaluate-issuer-trust.js.map +1 -0
  8. package/lib/commonjs/credential/issuance/03-start-user-authorization.js +119 -0
  9. package/lib/commonjs/credential/issuance/03-start-user-authorization.js.map +1 -0
  10. package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +6 -0
  11. package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -0
  12. package/lib/commonjs/credential/issuance/05-authorize-access.js +63 -0
  13. package/lib/commonjs/credential/issuance/05-authorize-access.js.map +1 -0
  14. package/lib/commonjs/credential/issuance/06-obtain-credential.js +128 -0
  15. package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -0
  16. package/lib/commonjs/credential/issuance/07-confirm-credential.js +6 -0
  17. package/lib/commonjs/credential/issuance/07-confirm-credential.js.map +1 -0
  18. package/lib/commonjs/credential/issuance/const.js +9 -0
  19. package/lib/commonjs/credential/issuance/const.js.map +1 -0
  20. package/lib/commonjs/credential/issuance/index.js +34 -0
  21. package/lib/commonjs/credential/issuance/index.js.map +1 -0
  22. package/lib/commonjs/credential/presentation/01-start-flow.js +55 -0
  23. package/lib/commonjs/credential/presentation/01-start-flow.js.map +1 -0
  24. package/lib/commonjs/credential/presentation/02-evaluate-rp-trust.js +32 -0
  25. package/lib/commonjs/credential/presentation/02-evaluate-rp-trust.js.map +1 -0
  26. package/lib/commonjs/credential/presentation/03-get-request-object.js +68 -0
  27. package/lib/commonjs/credential/presentation/03-get-request-object.js.map +1 -0
  28. package/lib/commonjs/credential/presentation/04-send-authorization-response.js +139 -0
  29. package/lib/commonjs/credential/presentation/04-send-authorization-response.js.map +1 -0
  30. package/lib/commonjs/credential/presentation/index.js +34 -0
  31. package/lib/commonjs/credential/presentation/index.js.map +1 -0
  32. package/lib/commonjs/{rp → credential/presentation}/types.js +17 -34
  33. package/lib/commonjs/credential/presentation/types.js.map +1 -0
  34. package/lib/commonjs/index.js +10 -61
  35. package/lib/commonjs/index.js.map +1 -1
  36. package/lib/commonjs/pid/index.js +1 -3
  37. package/lib/commonjs/pid/index.js.map +1 -1
  38. package/lib/commonjs/sd-jwt/index.js +1 -1
  39. package/lib/commonjs/sd-jwt/index.js.map +1 -1
  40. package/lib/commonjs/sd-jwt/types.js +1 -1
  41. package/lib/commonjs/sd-jwt/types.js.map +1 -1
  42. package/lib/commonjs/trust/chain.js +32 -4
  43. package/lib/commonjs/trust/chain.js.map +1 -1
  44. package/lib/commonjs/trust/index.js +105 -20
  45. package/lib/commonjs/trust/index.js.map +1 -1
  46. package/lib/commonjs/trust/types.js +54 -35
  47. package/lib/commonjs/trust/types.js.map +1 -1
  48. package/lib/commonjs/utils/crypto.js +5 -18
  49. package/lib/commonjs/utils/crypto.js.map +1 -1
  50. package/lib/commonjs/utils/misc.js +23 -0
  51. package/lib/commonjs/utils/misc.js.map +1 -0
  52. package/lib/commonjs/utils/par.js +86 -0
  53. package/lib/commonjs/utils/par.js.map +1 -0
  54. package/lib/module/credential/index.js +4 -0
  55. package/lib/module/credential/index.js.map +1 -0
  56. package/lib/module/credential/issuance/01-start-flow.js +2 -0
  57. package/lib/module/credential/issuance/01-start-flow.js.map +1 -0
  58. package/lib/module/credential/issuance/02-evaluate-issuer-trust.js +19 -0
  59. package/lib/module/credential/issuance/02-evaluate-issuer-trust.js.map +1 -0
  60. package/lib/module/credential/issuance/03-start-user-authorization.js +109 -0
  61. package/lib/module/credential/issuance/03-start-user-authorization.js.map +1 -0
  62. package/lib/module/credential/issuance/04-complete-user-authorization.js +2 -0
  63. package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -0
  64. package/lib/module/credential/issuance/05-authorize-access.js +55 -0
  65. package/lib/module/credential/issuance/05-authorize-access.js.map +1 -0
  66. package/lib/module/credential/issuance/06-obtain-credential.js +117 -0
  67. package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -0
  68. package/lib/module/credential/issuance/07-confirm-credential.js +2 -0
  69. package/lib/module/credential/issuance/07-confirm-credential.js.map +1 -0
  70. package/lib/module/credential/issuance/const.js +2 -0
  71. package/lib/module/credential/issuance/const.js.map +1 -0
  72. package/lib/module/credential/issuance/index.js +6 -0
  73. package/lib/module/credential/issuance/index.js.map +1 -0
  74. package/lib/module/credential/presentation/01-start-flow.js +46 -0
  75. package/lib/module/credential/presentation/01-start-flow.js.map +1 -0
  76. package/lib/module/credential/presentation/02-evaluate-rp-trust.js +25 -0
  77. package/lib/module/credential/presentation/02-evaluate-rp-trust.js.map +1 -0
  78. package/lib/module/credential/presentation/03-get-request-object.js +60 -0
  79. package/lib/module/credential/presentation/03-get-request-object.js.map +1 -0
  80. package/lib/module/credential/presentation/04-send-authorization-response.js +128 -0
  81. package/lib/module/credential/presentation/04-send-authorization-response.js.map +1 -0
  82. package/lib/module/credential/presentation/index.js +6 -0
  83. package/lib/module/credential/presentation/index.js.map +1 -0
  84. package/lib/module/credential/presentation/types.js +21 -0
  85. package/lib/module/credential/presentation/types.js.map +1 -0
  86. package/lib/module/index.js +4 -5
  87. package/lib/module/index.js.map +1 -1
  88. package/lib/module/pid/index.js +1 -2
  89. package/lib/module/pid/index.js.map +1 -1
  90. package/lib/module/sd-jwt/index.js +1 -1
  91. package/lib/module/sd-jwt/index.js.map +1 -1
  92. package/lib/module/sd-jwt/types.js +1 -1
  93. package/lib/module/sd-jwt/types.js.map +1 -1
  94. package/lib/module/trust/chain.js +30 -3
  95. package/lib/module/trust/chain.js.map +1 -1
  96. package/lib/module/trust/index.js +99 -16
  97. package/lib/module/trust/index.js.map +1 -1
  98. package/lib/module/trust/types.js +50 -31
  99. package/lib/module/trust/types.js.map +1 -1
  100. package/lib/module/utils/crypto.js +2 -15
  101. package/lib/module/utils/crypto.js.map +1 -1
  102. package/lib/module/utils/misc.js +17 -0
  103. package/lib/module/utils/misc.js.map +1 -0
  104. package/lib/module/utils/par.js +74 -0
  105. package/lib/module/utils/par.js.map +1 -0
  106. package/lib/typescript/credential/index.d.ts +4 -0
  107. package/lib/typescript/credential/index.d.ts.map +1 -0
  108. package/lib/typescript/credential/issuance/01-start-flow.d.ts +11 -0
  109. package/lib/typescript/credential/issuance/01-start-flow.d.ts.map +1 -0
  110. package/lib/typescript/credential/issuance/02-evaluate-issuer-trust.d.ts +18 -0
  111. package/lib/typescript/credential/issuance/02-evaluate-issuer-trust.d.ts.map +1 -0
  112. package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts +31 -0
  113. package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts.map +1 -0
  114. package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +16 -0
  115. package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -0
  116. package/lib/typescript/credential/issuance/05-authorize-access.d.ts +26 -0
  117. package/lib/typescript/credential/issuance/05-authorize-access.d.ts.map +1 -0
  118. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts +32 -0
  119. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -0
  120. package/lib/typescript/credential/issuance/07-confirm-credential.d.ts +11 -0
  121. package/lib/typescript/credential/issuance/07-confirm-credential.d.ts.map +1 -0
  122. package/lib/typescript/credential/issuance/const.d.ts +2 -0
  123. package/lib/typescript/credential/issuance/const.d.ts.map +1 -0
  124. package/lib/typescript/credential/issuance/index.d.ts +10 -0
  125. package/lib/typescript/credential/issuance/index.d.ts.map +1 -0
  126. package/lib/typescript/credential/presentation/01-start-flow.d.ts +20 -0
  127. package/lib/typescript/credential/presentation/01-start-flow.d.ts.map +1 -0
  128. package/lib/typescript/credential/presentation/02-evaluate-rp-trust.d.ts +18 -0
  129. package/lib/typescript/credential/presentation/02-evaluate-rp-trust.d.ts.map +1 -0
  130. package/lib/typescript/credential/presentation/03-get-request-object.d.ts +25 -0
  131. package/lib/typescript/credential/presentation/03-get-request-object.d.ts.map +1 -0
  132. package/lib/typescript/credential/presentation/04-send-authorization-response.d.ts +34 -0
  133. package/lib/typescript/credential/presentation/04-send-authorization-response.d.ts.map +1 -0
  134. package/lib/typescript/credential/presentation/index.d.ts +7 -0
  135. package/lib/typescript/credential/presentation/index.d.ts.map +1 -0
  136. package/lib/typescript/credential/presentation/types.d.ts +49 -0
  137. package/lib/typescript/credential/presentation/types.d.ts.map +1 -0
  138. package/lib/typescript/index.d.ts +4 -5
  139. package/lib/typescript/index.d.ts.map +1 -1
  140. package/lib/typescript/pid/index.d.ts +1 -2
  141. package/lib/typescript/pid/index.d.ts.map +1 -1
  142. package/lib/typescript/sd-jwt/index.d.ts +2 -2
  143. package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
  144. package/lib/typescript/sd-jwt/types.d.ts +5 -5
  145. package/lib/typescript/trust/chain.d.ts +12 -3
  146. package/lib/typescript/trust/chain.d.ts.map +1 -1
  147. package/lib/typescript/trust/index.d.ts +198 -24
  148. package/lib/typescript/trust/index.d.ts.map +1 -1
  149. package/lib/typescript/trust/types.d.ts +1299 -623
  150. package/lib/typescript/trust/types.d.ts.map +1 -1
  151. package/lib/typescript/utils/crypto.d.ts +1 -1
  152. package/lib/typescript/utils/crypto.d.ts.map +1 -1
  153. package/lib/typescript/utils/dpop.d.ts +2 -2
  154. package/lib/typescript/utils/misc.d.ts +8 -0
  155. package/lib/typescript/utils/misc.d.ts.map +1 -0
  156. package/lib/typescript/utils/par.d.ts +68 -0
  157. package/lib/typescript/utils/par.d.ts.map +1 -0
  158. package/package.json +2 -2
  159. package/src/credential/index.ts +4 -0
  160. package/src/credential/issuance/01-start-flow.ts +10 -0
  161. package/src/credential/issuance/02-evaluate-issuer-trust.ts +31 -0
  162. package/src/credential/issuance/03-start-user-authorization.ts +138 -0
  163. package/src/credential/issuance/04-complete-user-authorization.ts +17 -0
  164. package/src/credential/issuance/05-authorize-access.ts +92 -0
  165. package/src/credential/issuance/06-obtain-credential.ts +179 -0
  166. package/src/credential/issuance/07-confirm-credential.ts +14 -0
  167. package/src/credential/issuance/const.ts +2 -0
  168. package/src/credential/issuance/index.ts +32 -0
  169. package/src/credential/presentation/01-start-flow.ts +51 -0
  170. package/src/credential/presentation/02-evaluate-rp-trust.ts +33 -0
  171. package/src/credential/presentation/03-get-request-object.ts +85 -0
  172. package/src/credential/presentation/04-send-authorization-response.ts +168 -0
  173. package/src/credential/presentation/index.ts +26 -0
  174. package/src/credential/presentation/types.ts +27 -0
  175. package/src/index.ts +7 -28
  176. package/src/pid/index.ts +1 -2
  177. package/src/sd-jwt/index.ts +2 -2
  178. package/src/sd-jwt/types.ts +1 -1
  179. package/src/trust/chain.ts +45 -3
  180. package/src/trust/index.ts +136 -19
  181. package/src/trust/types.ts +57 -35
  182. package/src/utils/crypto.ts +2 -20
  183. package/src/utils/misc.ts +23 -0
  184. package/src/utils/par.ts +103 -0
  185. package/lib/commonjs/pid/issuing.js +0 -276
  186. package/lib/commonjs/pid/issuing.js.map +0 -1
  187. package/lib/commonjs/rp/__test__/index.test.js +0 -172
  188. package/lib/commonjs/rp/__test__/index.test.js.map +0 -1
  189. package/lib/commonjs/rp/index.js +0 -239
  190. package/lib/commonjs/rp/index.js.map +0 -1
  191. package/lib/commonjs/rp/types.js.map +0 -1
  192. package/lib/module/pid/issuing.js +0 -266
  193. package/lib/module/pid/issuing.js.map +0 -1
  194. package/lib/module/rp/__test__/index.test.js +0 -168
  195. package/lib/module/rp/__test__/index.test.js.map +0 -1
  196. package/lib/module/rp/index.js +0 -228
  197. package/lib/module/rp/index.js.map +0 -1
  198. package/lib/module/rp/types.js +0 -36
  199. package/lib/module/rp/types.js.map +0 -1
  200. package/lib/typescript/pid/issuing.d.ts +0 -57
  201. package/lib/typescript/pid/issuing.d.ts.map +0 -1
  202. package/lib/typescript/rp/__test__/index.test.d.ts +0 -2
  203. package/lib/typescript/rp/__test__/index.test.d.ts.map +0 -1
  204. package/lib/typescript/rp/index.d.ts +0 -43
  205. package/lib/typescript/rp/index.d.ts.map +0 -1
  206. package/lib/typescript/rp/types.d.ts +0 -122
  207. package/lib/typescript/rp/types.d.ts.map +0 -1
  208. package/src/pid/issuing.ts +0 -405
  209. package/src/rp/__test__/index.test.ts +0 -250
  210. package/src/rp/index.ts +0 -287
  211. package/src/rp/types.ts +0 -42
@@ -5,11 +5,74 @@ import {
5
5
  CredentialIssuerEntityConfiguration,
6
6
  RelyingPartyEntityConfiguration,
7
7
  EntityConfiguration,
8
+ EntityStatement,
8
9
  } from "./types";
9
- import { IoWalletError } from "../utils/errors";
10
- import { verifyTrustChain } from "./chain";
10
+ import { validateTrustChain, renewTrustChain } from "./chain";
11
+ import { hasStatus } from "../utils/misc";
11
12
 
12
- export { verifyTrustChain };
13
+ export type {
14
+ WalletProviderEntityConfiguration,
15
+ TrustAnchorEntityConfiguration,
16
+ CredentialIssuerEntityConfiguration,
17
+ RelyingPartyEntityConfiguration,
18
+ EntityConfiguration,
19
+ EntityStatement,
20
+ };
21
+
22
+ /**
23
+ * Verify a given trust chain is actually valid.
24
+ * It can handle fast chain renewal, which means we try to fetch a fresh version of each statement.
25
+ *
26
+ * @param trustAnchorEntity The entity configuration of the known trust anchor
27
+ * @param chain The chain of statements to be validate
28
+ * @param options.renewOnFail Whether to renew the provided chain if the validation fails at first. Default: true
29
+ * @param options.appFetch Fetch api implementation. Default: the built-in implementation
30
+ * @returns The result of the chain validation
31
+ * @throws {IoWalletError} When either validation or renewal fail
32
+ */
33
+ export async function verifyTrustChain(
34
+ trustAnchorEntity: TrustAnchorEntityConfiguration,
35
+ chain: string[],
36
+ {
37
+ appFetch = fetch,
38
+ renewOnFail = true,
39
+ }: { appFetch?: GlobalFetch["fetch"]; renewOnFail?: boolean } = {}
40
+ ): Promise<ReturnType<typeof validateTrustChain>> {
41
+ try {
42
+ return validateTrustChain(trustAnchorEntity, chain);
43
+ } catch (error) {
44
+ if (renewOnFail) {
45
+ const renewedChain = await renewTrustChain(chain, appFetch);
46
+ return validateTrustChain(trustAnchorEntity, renewedChain);
47
+ } else {
48
+ throw error;
49
+ }
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Fetch the signed entity configuration token for an entity
55
+ *
56
+ * @param entityBaseUrl The url of the entity to fetch
57
+ * @param param.appFetch (optional) fetch api implemention
58
+ * @returns The signed Entity Configuration token
59
+ */
60
+ export async function getSignedEntityConfiguration(
61
+ entityBaseUrl: string,
62
+ {
63
+ appFetch = fetch,
64
+ }: {
65
+ appFetch?: GlobalFetch["fetch"];
66
+ } = {}
67
+ ): Promise<string> {
68
+ const wellKnownUrl = `${entityBaseUrl}/.well-known/openid-federation`;
69
+
70
+ return await appFetch(wellKnownUrl, {
71
+ method: "GET",
72
+ })
73
+ .then(hasStatus(200))
74
+ .then((res) => res.text());
75
+ }
13
76
 
14
77
  /**
15
78
  * Fetch and parse the entity configuration document for a given federation entity.
@@ -77,24 +140,15 @@ async function fetchAndParseEntityConfiguration(
77
140
  appFetch?: GlobalFetch["fetch"];
78
141
  } = {}
79
142
  ) {
80
- const wellKnownUrl = `${entityBaseUrl}/.well-known/openid-federation`;
81
-
82
- const response = await appFetch(wellKnownUrl, {
83
- method: "GET",
143
+ const responseText = await getSignedEntityConfiguration(entityBaseUrl, {
144
+ appFetch,
84
145
  });
85
146
 
86
- if (response.status === 200) {
87
- const responseText = await response.text();
88
- const responseJwt = decodeJwt(responseText);
89
- return schema.parse({
90
- header: responseJwt.protectedHeader,
91
- payload: responseJwt.payload,
92
- });
93
- }
94
-
95
- throw new IoWalletError(
96
- `Unable to obtain Entity Configuration at ${wellKnownUrl}. Response code: ${response.status}`
97
- );
147
+ const responseJwt = decodeJwt(responseText);
148
+ return schema.parse({
149
+ header: responseJwt.protectedHeader,
150
+ payload: responseJwt.payload,
151
+ });
98
152
  }
99
153
 
100
154
  export const getWalletProviderEntityConfiguration = (
@@ -142,3 +196,66 @@ export const getEntityConfiguration = (
142
196
  options?: Parameters<typeof fetchAndParseEntityConfiguration>[2]
143
197
  ) =>
144
198
  fetchAndParseEntityConfiguration(entityBaseUrl, EntityConfiguration, options);
199
+
200
+ /**
201
+ * Fetch and parse the entity statement document for a given federation entity.
202
+ *
203
+ * @param accreditationBodyBaseUrl The base url of the accreditaion body which holds and signs the required entity statement
204
+ * @param subordinatedEntityBaseUrl The url that identifies the subordinate entity
205
+ * @param options.appFetch An optional instance of the http client to be used.
206
+ * @returns The parsed entity configuration object
207
+ * @throws {IoWalletError} If the http request fails
208
+ * @throws Parse error if the document is not in the expected shape.
209
+ */
210
+ export async function getEntityStatement(
211
+ accreditationBodyBaseUrl: string,
212
+ subordinatedEntityBaseUrl: string,
213
+ {
214
+ appFetch = fetch,
215
+ }: {
216
+ appFetch?: GlobalFetch["fetch"];
217
+ } = {}
218
+ ) {
219
+ const responseText = await getSignedEntityStatement(
220
+ accreditationBodyBaseUrl,
221
+ subordinatedEntityBaseUrl,
222
+ {
223
+ appFetch,
224
+ }
225
+ );
226
+
227
+ const responseJwt = decodeJwt(responseText);
228
+ return EntityStatement.parse({
229
+ header: responseJwt.protectedHeader,
230
+ payload: responseJwt.payload,
231
+ });
232
+ }
233
+
234
+ /**
235
+ * Fetch the entity statement document for a given federation entity.
236
+ *
237
+ * @param accreditationBodyBaseUrl The base url of the accreditaion body which holds and signs the required entity statement
238
+ * @param subordinatedEntityBaseUrl The url that identifies the subordinate entity
239
+ * @param options.appFetch An optional instance of the http client to be used.
240
+ * @returns The signed entity statement token
241
+ * @throws {IoWalletError} If the http request fails
242
+ */
243
+ export async function getSignedEntityStatement(
244
+ accreditationBodyBaseUrl: string,
245
+ subordinatedEntityBaseUrl: string,
246
+ {
247
+ appFetch = fetch,
248
+ }: {
249
+ appFetch?: GlobalFetch["fetch"];
250
+ } = {}
251
+ ) {
252
+ const url = `${accreditationBodyBaseUrl}/fetch?${new URLSearchParams({
253
+ sub: subordinatedEntityBaseUrl,
254
+ })}`;
255
+
256
+ return await appFetch(url, {
257
+ method: "GET",
258
+ })
259
+ .then(hasStatus(200))
260
+ .then((res) => res.text());
261
+ }
@@ -5,6 +5,15 @@ import * as z from "zod";
5
5
  export const TrustMark = z.object({ id: z.string(), trust_mark: z.string() });
6
6
  export type TrustMark = z.infer<typeof TrustMark>;
7
7
 
8
+ const RelyingPartyMetadata = z.object({
9
+ application_type: z.string().optional(),
10
+ client_id: z.string().optional(),
11
+ client_name: z.string().optional(),
12
+ jwks: z.object({ keys: z.array(JWK) }),
13
+ contacts: z.array(z.string()).optional(),
14
+ });
15
+ //.passthrough();
16
+
8
17
  // Display metadata for a credential, used by the issuer to
9
18
  // instruct the Wallet Solution on how to render the credential correctly
10
19
  type CredentialDisplayMetadata = z.infer<typeof CredentialDisplayMetadata>;
@@ -19,13 +28,28 @@ const CredentialDisplayMetadata = z.object({
19
28
  text_color: z.string(),
20
29
  });
21
30
 
31
+ type CredentialDefinitionMetadata = z.infer<
32
+ typeof CredentialDefinitionMetadata
33
+ >;
34
+ const CredentialDefinitionMetadata = z.object({
35
+ type: z.array(z.string()),
36
+ credentialSubject: z.record(
37
+ z.object({
38
+ mandatory: z.boolean(),
39
+ display: z.array(z.object({ name: z.string(), locale: z.string() })),
40
+ })
41
+ ),
42
+ });
43
+
22
44
  // Metadata for a credentia which i supported by a Issuer
23
45
  type SupportedCredentialMetadata = z.infer<typeof SupportedCredentialMetadata>;
24
46
  const SupportedCredentialMetadata = z.object({
47
+ id: z.string(),
25
48
  format: z.literal("vc+sd-jwt"),
26
49
  cryptographic_binding_methods_supported: z.array(z.string()),
27
50
  cryptographic_suites_supported: z.array(z.string()),
28
51
  display: z.array(CredentialDisplayMetadata),
52
+ credential_definition: CredentialDefinitionMetadata,
29
53
  });
30
54
 
31
55
  export type EntityStatement = z.infer<typeof EntityStatement>;
@@ -54,6 +78,20 @@ export const EntityConfigurationHeader = z.object({
54
78
  kid: z.string(),
55
79
  });
56
80
 
81
+ const FederationEntityMetadata = z
82
+ .object({
83
+ federation_fetch_endpoint: z.string().optional(),
84
+ federation_list_endpoint: z.string().optional(),
85
+ federation_resolve_endpoint: z.string().optional(),
86
+ federation_trust_mark_status_endpoint: z.string().optional(),
87
+ federation_trust_mark_list_endpoint: z.string().optional(),
88
+ homepage_uri: z.string().optional(),
89
+ policy_uri: z.string().optional(),
90
+ logo_uri: z.string().optional(),
91
+ contacts: z.array(z.string()).optional(),
92
+ })
93
+ .passthrough();
94
+
57
95
  // Structuire common to every Entity Configuration document
58
96
  const BaseEntityConfiguration = z.object({
59
97
  header: EntityConfigurationHeader,
@@ -68,19 +106,7 @@ const BaseEntityConfiguration = z.object({
68
106
  }),
69
107
  metadata: z
70
108
  .object({
71
- federation_entity: z
72
- .object({
73
- federation_fetch_endpoint: z.string().optional(),
74
- federation_list_endpoint: z.string().optional(),
75
- federation_resolve_endpoint: z.string().optional(),
76
- federation_trust_mark_status_endpoint: z.string().optional(),
77
- federation_trust_mark_list_endpoint: z.string().optional(),
78
- homepage_uri: z.string().optional(),
79
- policy_uri: z.string().optional(),
80
- logo_uri: z.string().optional(),
81
- contacts: z.array(z.string()).optional(),
82
- })
83
- .passthrough(),
109
+ federation_entity: FederationEntityMetadata,
84
110
  })
85
111
  .passthrough(),
86
112
  authority_hints: z.array(z.string()).optional(),
@@ -113,6 +139,24 @@ export const CredentialIssuerEntityConfiguration = BaseEntityConfiguration.and(
113
139
  credentials_supported: z.array(SupportedCredentialMetadata),
114
140
  jwks: z.object({ keys: z.array(JWK) }),
115
141
  }),
142
+ /** Credential Issuers act as Relying Party
143
+ when they require the presentation of other credentials.
144
+ This does not apply for PID issuance, which requires CIE authz. */
145
+ wallet_relying_party: RelyingPartyMetadata.optional(),
146
+ }),
147
+ }),
148
+ })
149
+ );
150
+
151
+ // Entity configuration for a Relying Party
152
+ export type RelyingPartyEntityConfiguration = z.infer<
153
+ typeof RelyingPartyEntityConfiguration
154
+ >;
155
+ export const RelyingPartyEntityConfiguration = BaseEntityConfiguration.and(
156
+ z.object({
157
+ payload: z.object({
158
+ metadata: z.object({
159
+ wallet_relying_party: RelyingPartyMetadata,
116
160
  }),
117
161
  }),
118
162
  })
@@ -145,28 +189,6 @@ export const WalletProviderEntityConfiguration = BaseEntityConfiguration.and(
145
189
  })
146
190
  );
147
191
 
148
- // Entity configuration for a Relying Party
149
- export type RelyingPartyEntityConfiguration = z.infer<
150
- typeof RelyingPartyEntityConfiguration
151
- >;
152
- export const RelyingPartyEntityConfiguration = BaseEntityConfiguration.and(
153
- z.object({
154
- payload: z.object({
155
- metadata: z.object({
156
- wallet_relying_party: z
157
- .object({
158
- application_type: z.string().optional(),
159
- client_id: z.string().optional(),
160
- client_name: z.string().optional(),
161
- jwks: z.object({ keys: z.array(JWK) }),
162
- contacts: z.array(z.string()).optional(),
163
- })
164
- .passthrough(),
165
- }),
166
- }),
167
- })
168
- );
169
-
170
192
  // Maps any entity configuration by the union of every possible shapes
171
193
  export type EntityConfiguration = z.infer<typeof EntityConfiguration>;
172
194
  export const EntityConfiguration = z.union(
@@ -46,24 +46,6 @@ export const createCryptoContextFor = (keytag: string): CryptoContext => {
46
46
  };
47
47
  };
48
48
 
49
- // Wraps finally for async expressions
50
- const asyncFinally =
51
- <A extends Array<unknown>, R>(
52
- fn: (...args: A) => Promise<R>,
53
- onFinally: () => void | Promise<void>
54
- ) =>
55
- async (...args: A): Promise<R> => {
56
- try {
57
- return await fn(...args);
58
- // ^^^^^ return await is usually to be avoided,
59
- // in this case is needed for the finally{} statement to be executed correctly
60
- } catch (error) {
61
- throw error;
62
- } finally {
63
- await onFinally();
64
- }
65
- };
66
-
67
49
  /**
68
50
  * Executes the input function injecting an ephemeral crypto context.
69
51
  * An ephemeral crypto context is a context which is bound to a key
@@ -72,12 +54,12 @@ const asyncFinally =
72
54
  * @param fn The procedure to be executed
73
55
  * @returns The returned value of the input procedure.
74
56
  */
75
- export const useEphemeralKey = async <R>(
57
+ export const withEphemeralKey = async <R>(
76
58
  fn: (ephemeralContext: CryptoContext) => Promise<R>
77
59
  ): Promise<R> => {
78
60
  // Use an ephemeral key to be destroyed after use
79
61
  const keytag = `ephemeral-${uuid.v4()}`;
80
62
  await generate(keytag);
81
63
  const ephemeralContext = createCryptoContextFor(keytag);
82
- return asyncFinally(fn, () => deleteKey(keytag))(ephemeralContext);
64
+ return fn(ephemeralContext).finally(() => deleteKey(keytag));
83
65
  };
@@ -0,0 +1,23 @@
1
+ import { IoWalletError } from "./errors";
2
+
3
+ /**
4
+ * Check if a response is in the expected status, other
5
+ * @param status The expected status
6
+ * @returns The given response object
7
+ */
8
+ export const hasStatus =
9
+ (status: number) =>
10
+ (res: Response): Response => {
11
+ if (res.status !== status) {
12
+ throw new IoWalletError(
13
+ `Http request failed. Expected ${status}, got ${res.status}, url: ${res.url}`
14
+ );
15
+ }
16
+ return res;
17
+ };
18
+
19
+ // extract a type from an async function output
20
+ // helpful to bind the input of a function to the output of another
21
+ export type Out<FN> = FN extends (...args: any[]) => Promise<any>
22
+ ? Awaited<ReturnType<FN>>
23
+ : never;
@@ -0,0 +1,103 @@
1
+ import {
2
+ sha256ToBase64,
3
+ type CryptoContext,
4
+ SignJWT,
5
+ } from "@pagopa/io-react-native-jwt";
6
+ import uuid from "react-native-uuid";
7
+ import * as z from "zod";
8
+ import * as WalletInstanceAttestation from "../wallet-instance-attestation";
9
+ import { hasStatus } from "./misc";
10
+
11
+ export type AuthorizationDetail = z.infer<typeof AuthorizationDetail>;
12
+ export const AuthorizationDetail = z.object({
13
+ credential_definition: z.object({
14
+ type: z.string(),
15
+ }),
16
+ format: z.literal("vc+sd-jwt"),
17
+ type: z.literal("openid_credential"),
18
+ });
19
+
20
+ export type AuthorizationDetails = z.infer<typeof AuthorizationDetails>;
21
+ export const AuthorizationDetails = z.array(AuthorizationDetail);
22
+
23
+ /**
24
+ * Make a PAR request to the issuer and return the response url
25
+ */
26
+ export const makeParRequest =
27
+ ({
28
+ wiaCryptoContext,
29
+ appFetch = fetch,
30
+ }: {
31
+ wiaCryptoContext: CryptoContext;
32
+ appFetch?: GlobalFetch["fetch"];
33
+ }) =>
34
+ async (
35
+ clientId: string,
36
+ codeVerifier: string,
37
+ walletProviderBaseUrl: string,
38
+ parEndpoint: string,
39
+ walletInstanceAttestation: string,
40
+ authorizationDetails: AuthorizationDetails,
41
+ assertionType: string
42
+ ): Promise<string> => {
43
+ const wiaPublicKey = await wiaCryptoContext.getPublicKey();
44
+
45
+ const parUrl = new URL(parEndpoint);
46
+ const aud = `${parUrl.protocol}//${parUrl.hostname}`;
47
+
48
+ const iss = WalletInstanceAttestation.decode(walletInstanceAttestation)
49
+ .payload.cnf.jwk.kid;
50
+
51
+ /** A code challenge is provided so that the PAR is bound
52
+ to the subsequent authorization code request
53
+ @see https://datatracker.ietf.org/doc/html/rfc9126#name-request */
54
+ const codeChallengeMethod = "s256";
55
+ const codeChallenge = await sha256ToBase64(codeVerifier);
56
+
57
+ /** The PAR request token is signed used the Wallet Instance Attestation key.
58
+ The signature can be verified by reading the public key from the key set shippet
59
+ with the it will ship the Wallet Instance Attestation.
60
+ The key is matched by its kid */
61
+ const signedJwtForPar = await new SignJWT(wiaCryptoContext)
62
+ .setProtectedHeader({
63
+ kid: wiaPublicKey.kid,
64
+ })
65
+ .setPayload({
66
+ iss,
67
+ aud,
68
+ jti: `${uuid.v4()}`,
69
+ client_assertion_type: assertionType,
70
+ authorization_details: authorizationDetails,
71
+ response_type: "code",
72
+ redirect_uri: walletProviderBaseUrl,
73
+ state: `${uuid.v4()}`,
74
+ client_id: clientId,
75
+ code_challenge_method: codeChallengeMethod,
76
+ code_challenge: codeChallenge,
77
+ })
78
+ .setIssuedAt()
79
+ .setExpirationTime("1h")
80
+ .sign();
81
+
82
+ /** The request body for the Pushed Authorization Request */
83
+ var formBody = new URLSearchParams({
84
+ response_type: "code",
85
+ client_id: clientId,
86
+ code_challenge: codeChallenge,
87
+ code_challenge_method: "S256",
88
+ client_assertion_type: assertionType,
89
+ client_assertion: walletInstanceAttestation,
90
+ request: signedJwtForPar,
91
+ });
92
+
93
+ return await appFetch(parEndpoint, {
94
+ method: "POST",
95
+ headers: {
96
+ "Content-Type": "application/x-www-form-urlencoded",
97
+ },
98
+ body: formBody.toString(),
99
+ })
100
+ .then(hasStatus(201))
101
+ .then((res) => res.json())
102
+ .then((result) => result.request_uri);
103
+ };