@pagopa/io-react-native-wallet 2.0.0-next.2 → 2.0.0-next.4

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 (146) hide show
  1. package/lib/commonjs/credential/issuance/03-start-user-authorization.js +38 -24
  2. package/lib/commonjs/credential/issuance/03-start-user-authorization.js.map +1 -1
  3. package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +75 -57
  4. package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -1
  5. package/lib/commonjs/credential/issuance/05-authorize-access.js +6 -10
  6. package/lib/commonjs/credential/issuance/05-authorize-access.js.map +1 -1
  7. package/lib/commonjs/credential/issuance/06-obtain-credential.js +43 -11
  8. package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
  9. package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +51 -48
  10. package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
  11. package/lib/commonjs/credential/issuance/README.md +77 -45
  12. package/lib/commonjs/credential/issuance/const.js +1 -1
  13. package/lib/commonjs/credential/issuance/types.js +17 -10
  14. package/lib/commonjs/credential/issuance/types.js.map +1 -1
  15. package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js +6 -13
  16. package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
  17. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +10 -11
  18. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
  19. package/lib/commonjs/credential/presentation/types.js +1 -1
  20. package/lib/commonjs/credential/presentation/types.js.map +1 -1
  21. package/lib/commonjs/credential/status/README.md +0 -1
  22. package/lib/commonjs/sd-jwt/__test__/index.test.js +11 -15
  23. package/lib/commonjs/sd-jwt/__test__/index.test.js.map +1 -1
  24. package/lib/commonjs/sd-jwt/__test__/types.test.js +5 -2
  25. package/lib/commonjs/sd-jwt/__test__/types.test.js.map +1 -1
  26. package/lib/commonjs/sd-jwt/__test__/utils.test.js +37 -0
  27. package/lib/commonjs/sd-jwt/__test__/utils.test.js.map +1 -0
  28. package/lib/commonjs/sd-jwt/index.js +26 -1
  29. package/lib/commonjs/sd-jwt/index.js.map +1 -1
  30. package/lib/commonjs/sd-jwt/types.js +71 -8
  31. package/lib/commonjs/sd-jwt/types.js.map +1 -1
  32. package/lib/commonjs/sd-jwt/utils.js +64 -0
  33. package/lib/commonjs/sd-jwt/utils.js.map +1 -0
  34. package/lib/commonjs/trust/types.js +18 -13
  35. package/lib/commonjs/trust/types.js.map +1 -1
  36. package/lib/commonjs/utils/par.js +32 -22
  37. package/lib/commonjs/utils/par.js.map +1 -1
  38. package/lib/commonjs/utils/pop.js +1 -1
  39. package/lib/commonjs/utils/pop.js.map +1 -1
  40. package/lib/commonjs/wallet-instance-attestation/types.js +4 -1
  41. package/lib/commonjs/wallet-instance-attestation/types.js.map +1 -1
  42. package/lib/module/credential/issuance/03-start-user-authorization.js +38 -24
  43. package/lib/module/credential/issuance/03-start-user-authorization.js.map +1 -1
  44. package/lib/module/credential/issuance/04-complete-user-authorization.js +76 -58
  45. package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -1
  46. package/lib/module/credential/issuance/05-authorize-access.js +6 -10
  47. package/lib/module/credential/issuance/05-authorize-access.js.map +1 -1
  48. package/lib/module/credential/issuance/06-obtain-credential.js +44 -12
  49. package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
  50. package/lib/module/credential/issuance/07-verify-and-parse-credential.js +51 -48
  51. package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
  52. package/lib/module/credential/issuance/README.md +77 -45
  53. package/lib/module/credential/issuance/const.js +1 -1
  54. package/lib/module/credential/issuance/types.js +13 -8
  55. package/lib/module/credential/issuance/types.js.map +1 -1
  56. package/lib/module/credential/presentation/07-evaluate-dcql-query.js +6 -13
  57. package/lib/module/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
  58. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +10 -11
  59. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
  60. package/lib/module/credential/presentation/types.js +1 -1
  61. package/lib/module/credential/presentation/types.js.map +1 -1
  62. package/lib/module/credential/status/README.md +0 -1
  63. package/lib/module/sd-jwt/__test__/index.test.js +11 -16
  64. package/lib/module/sd-jwt/__test__/index.test.js.map +1 -1
  65. package/lib/module/sd-jwt/__test__/types.test.js +5 -2
  66. package/lib/module/sd-jwt/__test__/types.test.js.map +1 -1
  67. package/lib/module/sd-jwt/__test__/utils.test.js +35 -0
  68. package/lib/module/sd-jwt/__test__/utils.test.js.map +1 -0
  69. package/lib/module/sd-jwt/index.js +7 -1
  70. package/lib/module/sd-jwt/index.js.map +1 -1
  71. package/lib/module/sd-jwt/types.js +70 -7
  72. package/lib/module/sd-jwt/types.js.map +1 -1
  73. package/lib/module/sd-jwt/utils.js +57 -0
  74. package/lib/module/sd-jwt/utils.js.map +1 -0
  75. package/lib/module/trust/types.js +18 -13
  76. package/lib/module/trust/types.js.map +1 -1
  77. package/lib/module/utils/par.js +29 -20
  78. package/lib/module/utils/par.js.map +1 -1
  79. package/lib/module/utils/pop.js +1 -1
  80. package/lib/module/utils/pop.js.map +1 -1
  81. package/lib/module/wallet-instance-attestation/types.js +4 -1
  82. package/lib/module/wallet-instance-attestation/types.js.map +1 -1
  83. package/lib/typescript/client/generated/wallet-provider.d.ts +12 -12
  84. package/lib/typescript/credential/issuance/01-start-flow.d.ts +2 -2
  85. package/lib/typescript/credential/issuance/01-start-flow.d.ts.map +1 -1
  86. package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts +7 -6
  87. package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts.map +1 -1
  88. package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +7 -14
  89. package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -1
  90. package/lib/typescript/credential/issuance/05-authorize-access.d.ts.map +1 -1
  91. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts +10 -5
  92. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -1
  93. package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts +3 -2
  94. package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
  95. package/lib/typescript/credential/issuance/const.d.ts +1 -1
  96. package/lib/typescript/credential/issuance/types.d.ts +49 -26
  97. package/lib/typescript/credential/issuance/types.d.ts.map +1 -1
  98. package/lib/typescript/credential/presentation/01-start-flow.d.ts +2 -2
  99. package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts +4 -3
  100. package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts.map +1 -1
  101. package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts +9 -5
  102. package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -1
  103. package/lib/typescript/credential/presentation/types.d.ts +3 -4
  104. package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
  105. package/lib/typescript/credential/status/types.d.ts +4 -4
  106. package/lib/typescript/pid/sd-jwt/types.d.ts +7 -7
  107. package/lib/typescript/sd-jwt/__test__/utils.test.d.ts +2 -0
  108. package/lib/typescript/sd-jwt/__test__/utils.test.d.ts.map +1 -0
  109. package/lib/typescript/sd-jwt/index.d.ts +69 -28
  110. package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
  111. package/lib/typescript/sd-jwt/types.d.ts +264 -31
  112. package/lib/typescript/sd-jwt/types.d.ts.map +1 -1
  113. package/lib/typescript/sd-jwt/utils.d.ts +18 -0
  114. package/lib/typescript/sd-jwt/utils.d.ts.map +1 -0
  115. package/lib/typescript/trust/build-chain.d.ts +30 -14
  116. package/lib/typescript/trust/build-chain.d.ts.map +1 -1
  117. package/lib/typescript/trust/types.d.ts +322 -158
  118. package/lib/typescript/trust/types.d.ts.map +1 -1
  119. package/lib/typescript/utils/par.d.ts +29 -13
  120. package/lib/typescript/utils/par.d.ts.map +1 -1
  121. package/lib/typescript/wallet-instance-attestation/types.d.ts +9 -9
  122. package/lib/typescript/wallet-instance-attestation/types.d.ts.map +1 -1
  123. package/package.json +1 -1
  124. package/src/credential/issuance/01-start-flow.ts +2 -2
  125. package/src/credential/issuance/03-start-user-authorization.ts +57 -38
  126. package/src/credential/issuance/04-complete-user-authorization.ts +79 -85
  127. package/src/credential/issuance/05-authorize-access.ts +5 -11
  128. package/src/credential/issuance/06-obtain-credential.ts +56 -23
  129. package/src/credential/issuance/07-verify-and-parse-credential.ts +54 -62
  130. package/src/credential/issuance/README.md +77 -45
  131. package/src/credential/issuance/const.ts +1 -1
  132. package/src/credential/issuance/types.ts +19 -8
  133. package/src/credential/presentation/07-evaluate-dcql-query.ts +16 -17
  134. package/src/credential/presentation/07-evaluate-input-descriptor.ts +19 -16
  135. package/src/credential/presentation/types.ts +1 -2
  136. package/src/credential/status/README.md +0 -1
  137. package/src/sd-jwt/__test__/index.test.ts +8 -29
  138. package/src/sd-jwt/__test__/types.test.ts +6 -2
  139. package/src/sd-jwt/__test__/utils.test.ts +37 -0
  140. package/src/sd-jwt/index.ts +7 -1
  141. package/src/sd-jwt/types.ts +68 -7
  142. package/src/sd-jwt/utils.ts +73 -0
  143. package/src/trust/types.ts +23 -17
  144. package/src/utils/par.ts +37 -21
  145. package/src/utils/pop.ts +1 -1
  146. package/src/wallet-instance-attestation/types.ts +3 -1
@@ -6,7 +6,7 @@ There's a fork in the flow which is based on the type of the credential that is
6
6
  This is due to the fact that eID credentials require a different authorization flow than other credentials, which is accomplished by a strong authentication method like SPID or CIE.
7
7
  Credentials instead require a simpler authorization flow and they require other credentials to be presented in order to be issued.
8
8
 
9
- The supported credentials are defined in the entity configuration of the issuer which is evaluted and parsed in the `evaluateIssuerTrust` step.
9
+ The supported credentials are defined in the entity configuration of the issuer which is evaluted and parsed in the `evaluateIssuerTrust` step. Available credentials are identified with a unique `credential_configuration_id`, that must be used when requesting authorization. The Authorization Server returns an array of **credential identifiers** that map to the `credential_configuration_id` provided: to obtain the credential, one of the credential identifiers (or all of them) must be requested to the credential endpoint.
10
10
 
11
11
  ## Sequence Diagram
12
12
 
@@ -96,17 +96,13 @@ const walletInstanceAttestation =
96
96
  appFetch,
97
97
  });
98
98
 
99
- const credentialType = "someCredential"; // Let's assume this is the credential type
100
-
101
- const eid = {
99
+ const pid = {
102
100
  credential: "example",
103
101
  parsedCredential: "example"
104
102
  keyTag: "example";
105
- credentialType: "eid";
103
+ credentialType: "PersonIdentificationData";
106
104
  };
107
105
 
108
- const eidCryptoContext = createCryptoContextFor(eid.keyTag);
109
-
110
106
  // Create credential crypto context
111
107
  const credentialKeyTag = uuidv4().toString();
112
108
  await generate(credentialKeyTag); // Let's assume this function generates a new hardware-backed key pair
@@ -115,22 +111,26 @@ const credentialCryptoContext = createCryptoContextFor(credentialKeyTag);
115
111
  // Start the issuance flow
116
112
  const startFlow: Credential.Issuance.StartFlow = () => ({
117
113
  issuerUrl: WALLET_EAA_PROVIDER_BASE_URL,
118
- credentialType,
114
+ credentialId: "someCredentialId",
119
115
  });
120
116
 
121
- const { issuerUrl } = startFlow();
117
+ const { issuerUrl, credentialId } = startFlow();
122
118
 
123
119
  // Evaluate issuer trust
124
120
  const { issuerConf } = await Credential.Issuance.evaluateIssuerTrust(issuerUrl);
125
121
 
126
122
  // Start user authorization
127
- const { issuerRequestUri, clientId, codeVerifier, credentialDefinition } =
128
- await Credential.Issuance.startUserAuthorization(issuerConf, credentialType, {
129
- walletInstanceAttestation,
130
- redirectUri,
131
- wiaCryptoContext,
132
- appFetch,
133
- });
123
+ const { issuerRequestUri, clientId, codeVerifier } =
124
+ await Credential.Issuance.startUserAuthorization(
125
+ issuerConf,
126
+ [credentialId],
127
+ {
128
+ walletInstanceAttestation,
129
+ redirectUri: REDIRECT_URI,
130
+ wiaCryptoContext,
131
+ appFetch,
132
+ }
133
+ );
134
134
 
135
135
  const requestObject =
136
136
  await Credential.Issuance.getRequestedCredentialToBePresented(
@@ -140,13 +140,12 @@ const requestObject =
140
140
  appFetch
141
141
  );
142
142
 
143
- // The app here should ask the user to confirm the required data contained in the requestObject
144
-
145
143
  // Complete the user authorization via form_post.jwt mode
146
144
  const { code } =
147
145
  await Credential.Issuance.completeUserAuthorizationWithFormPostJwtMode(
148
146
  requestObject,
149
- { wiaCryptoContext, pidCryptoContext, pid, walletInstanceAttestation }
147
+ pid.credential,
148
+ { wiaCryptoContext, pidCryptoContext: createCryptoContextFor(pid.keyTag) }
150
149
  );
151
150
 
152
151
  // Generate the DPoP context which will be used for the whole issuance flow
@@ -157,7 +156,7 @@ const { accessToken } = await Credential.Issuance.authorizeAccess(
157
156
  issuerConf,
158
157
  code,
159
158
  clientId,
160
- redirectUri,
159
+ redirectUri: REDIRECT_URI,
161
160
  codeVerifier,
162
161
  {
163
162
  walletInstanceAttestation,
@@ -167,12 +166,19 @@ const { accessToken } = await Credential.Issuance.authorizeAccess(
167
166
  }
168
167
  );
169
168
 
170
- // Obtain the credential
171
- const { credential, format } = await Credential.Issuance.obtainCredential(
169
+ // For simplicity, in this example flow we work on a single credential.
170
+ const { credential_configuration_id, credential_identifiers } =
171
+ accessToken.authorization_details[0]!;
172
+
173
+ // Obtain the credential
174
+ const { credential } = await Credential.Issuance.obtainCredential(
172
175
  issuerConf,
173
176
  accessToken,
174
177
  clientId,
175
- credentialDefinition,
178
+ {
179
+ credential_configuration_id,
180
+ credential_identifier: credential_identifiers[0],
181
+ },
176
182
  {
177
183
  credentialCryptoContext,
178
184
  dPopCryptoContext,
@@ -184,22 +190,29 @@ const { credential, format } = await Credential.Issuance.obtainCredential(
184
190
  * Parse and verify the credential. The ignoreMissingAttributes flag must be set to false or omitted in production.
185
191
  * WARNING: includeUndefinedAttributes should not be set to true in production in order to get only claims explicitly declared by the issuer.
186
192
  */
187
- const { parsedCredential } = await Credential.Issuance.verifyAndParseCredential(
188
- issuerConf,
189
- credential,
190
- format,
191
- {
192
- credentialCryptoContext,
193
- ignoreMissingAttributes: true,
194
- includeUndefinedAttributes: false
195
- }
196
- );
193
+ const { parsedCredential } =
194
+ await Credential.Issuance.verifyAndParseCredential(
195
+ issuerConf,
196
+ credential,
197
+ credential_configuration_id,
198
+ {
199
+ credentialCryptoContext,
200
+ ignoreMissingAttributes: true,
201
+ includeUndefinedAttributes: false
202
+ }
203
+ );
204
+
205
+ const credentialType =
206
+ issuerConf.openid_credential_issuer.credential_configurations_supported[
207
+ credential_configuration_id
208
+ ].scope;
197
209
 
198
210
  return {
199
211
  parsedCredential,
200
212
  credential,
201
213
  keyTag: credentialKeyTag,
202
214
  credentialType,
215
+ credentialConfigurationId: credential_configuration_id,
203
216
  };
204
217
  ```
205
218
 
@@ -251,11 +264,10 @@ const credentialCryptoContext = createCryptoContextFor(credentialKeyTag);
251
264
  // Start the issuance flow
252
265
  const startFlow: Credential.Issuance.StartFlow = () => ({
253
266
  issuerUrl: WALLET_EID_PROVIDER_BASE_URL,
254
- credentialType: "PersonIdentificationData",
255
- appFetch,
267
+ credentialId: "dc_sd_jwt_PersonIdentificationData",
256
268
  });
257
269
 
258
- const { issuerUrl } = startFlow();
270
+ const { issuerUrl, credentialId } = startFlow();
259
271
 
260
272
  // Evaluate issuer trust
261
273
  const { issuerConf } = await Credential.Issuance.evaluateIssuerTrust(
@@ -265,12 +277,16 @@ const { issuerConf } = await Credential.Issuance.evaluateIssuerTrust(
265
277
 
266
278
  // Start user authorization
267
279
  const { issuerRequestUri, clientId, codeVerifier, credentialDefinition } =
268
- await Credential.Issuance.startUserAuthorization(issuerConf, credentialType, {
269
- walletInstanceAttestation,
270
- redirectUri,
271
- wiaCryptoContext,
272
- appFetch,
273
- });
280
+ await Credential.Issuance.startUserAuthorization(
281
+ issuerConf,
282
+ [credentialId], // Request authorization for one or more credentials
283
+ {
284
+ walletInstanceAttestation,
285
+ redirectUri,
286
+ wiaCryptoContext,
287
+ appFetch,
288
+ }
289
+ );
274
290
 
275
291
  // Complete the authorization process with query mode with the authorizationContext which opens the browser
276
292
  const { code } =
@@ -301,12 +317,27 @@ const { accessToken } = await Credential.Issuance.authorizeAccess(
301
317
  }
302
318
  );
303
319
 
320
+
321
+ const [pidCredentialDefinition] = credentialDefinition;
322
+
323
+ // Extract the credential_identifier(s) from the access token
324
+ // For each one of them, a credential can be obtained by calling `obtainCredential`
325
+ const { credential_configuration_id, credential_identifiers } =
326
+ accessToken.authorization_details.find(
327
+ (authDetails) =>
328
+ authDetails.credential_configuration_id ===
329
+ pidCredentialDefinition.credential_configuration_id
330
+ );
331
+
304
332
  // Obtain che eID credential
305
333
  const { credential, format } = await Credential.Issuance.obtainCredential(
306
334
  issuerConf,
307
335
  accessToken,
308
336
  clientId,
309
- credentialDefinition,
337
+ {
338
+ credential_configuration_id,
339
+ credential_identifier: credential_identifiers.at(0),
340
+ },
310
341
  {
311
342
  credentialCryptoContext,
312
343
  dPopCryptoContext,
@@ -318,15 +349,16 @@ const { credential, format } = await Credential.Issuance.obtainCredential(
318
349
  const { parsedCredential, issuedAt, expiration } = await Credential.Issuance.verifyAndParseCredential(
319
350
  issuerConf,
320
351
  credential,
321
- format,
352
+ credential_configuration_id,
322
353
  { credentialCryptoContext }
323
354
  );
324
355
 
325
356
  return {
326
357
  parsedCredential,
327
358
  credential,
359
+ credentialConfigurationId: credential_configuration_id
360
+ credentialType: "PersonIdentificationData",
328
361
  keyTag: credentialKeyTag,
329
- credentialType,
330
362
  issuedAt,
331
363
  expiration
332
364
  };
@@ -6,6 +6,6 @@ export type SupportedCredentialFormat = z.infer<
6
6
  typeof SupportedCredentialFormat
7
7
  >;
8
8
  export const SupportedCredentialFormat = z.union([
9
- z.literal("vc+sd-jwt"),
9
+ z.literal("dc+sd-jwt"),
10
10
  z.literal("vc+mdoc-cbor"),
11
11
  ]);
@@ -1,14 +1,18 @@
1
- import { AuthorizationDetail } from "../../utils/par";
2
1
  import * as z from "zod";
3
- import { SupportedCredentialFormat } from "./const";
2
+
3
+ export type AuthorizationDetail = z.infer<typeof AuthorizationDetail>;
4
+ export const AuthorizationDetail = z.object({
5
+ type: z.literal("openid_credential"),
6
+ credential_configuration_id: z.string(),
7
+ credential_identifiers: z.array(z.string()),
8
+ });
4
9
 
5
10
  export type TokenResponse = z.infer<typeof TokenResponse>;
6
11
 
7
12
  export const TokenResponse = z.object({
8
13
  access_token: z.string(),
14
+ refresh_token: z.string().optional(),
9
15
  authorization_details: z.array(AuthorizationDetail),
10
- c_nonce: z.string(),
11
- c_nonce_expires_in: z.number(),
12
16
  expires_in: z.number(),
13
17
  token_type: z.string(),
14
18
  });
@@ -16,10 +20,12 @@ export const TokenResponse = z.object({
16
20
  export type CredentialResponse = z.infer<typeof CredentialResponse>;
17
21
 
18
22
  export const CredentialResponse = z.object({
19
- c_nonce: z.string(),
20
- c_nonce_expires_in: z.number(),
21
- credential: z.string(),
22
- format: SupportedCredentialFormat,
23
+ credentials: z.array(
24
+ z.object({
25
+ credential: z.string(),
26
+ })
27
+ ),
28
+ notification_id: z.string().optional(),
23
29
  });
24
30
 
25
31
  /**
@@ -30,3 +36,8 @@ export const ResponseUriResultShape = z.object({
30
36
  });
31
37
 
32
38
  export type ResponseMode = "query" | "form_post.jwt";
39
+
40
+ export type NonceResponse = z.infer<typeof NonceResponse>;
41
+ export const NonceResponse = z.object({
42
+ c_nonce: z.string(),
43
+ });
@@ -2,9 +2,9 @@ import { DcqlQuery, DcqlError, DcqlQueryResult } from "dcql";
2
2
  import { isValiError } from "valibot";
3
3
  import { decode, prepareVpToken } from "../../sd-jwt";
4
4
  import type { Disclosure } from "../../sd-jwt/types";
5
- import { createCryptoContextFor } from "../../utils/crypto";
6
5
  import type { RemotePresentation } from "./types";
7
6
  import { CredentialsNotFoundError, type NotFoundDetail } from "./errors";
7
+ import type { CryptoContext } from "@pagopa/io-react-native-jwt";
8
8
 
9
9
  /**
10
10
  * The purpose for the credential request by the RP.
@@ -15,13 +15,13 @@ type CredentialPurpose = {
15
15
  };
16
16
 
17
17
  export type EvaluateDcqlQuery = (
18
- credentialsSdJwt: [string /* keyTag */, string /* credential */][],
18
+ credentialsSdJwt: [CryptoContext, string /* credential */][],
19
19
  query: DcqlQuery.Input
20
20
  ) => {
21
21
  id: string;
22
22
  vct: string;
23
23
  credential: string;
24
- keyTag: string;
24
+ cryptoContext: CryptoContext;
25
25
  requiredDisclosures: Disclosure[];
26
26
  purposes: CredentialPurpose[];
27
27
  }[];
@@ -30,7 +30,7 @@ export type PrepareRemotePresentations = (
30
30
  credentials: {
31
31
  id: string;
32
32
  credential: string;
33
- keyTag: string;
33
+ cryptoContext: CryptoContext;
34
34
  requestedClaims: string[];
35
35
  }[],
36
36
  nonce: string,
@@ -55,11 +55,6 @@ const mapCredentialToObject = (jwt: string) => {
55
55
  const { sdJwt, disclosures } = decode(jwt);
56
56
  const credentialFormat = sdJwt.header.typ;
57
57
 
58
- // TODO [SIW-2082]: support MDOC credentials
59
- if (credentialFormat !== "vc+sd-jwt") {
60
- throw new Error(`Unsupported credential format: ${credentialFormat}`);
61
- }
62
-
63
58
  return {
64
59
  vct: sdJwt.payload.vct,
65
60
  credential_format: credentialFormat,
@@ -100,7 +95,10 @@ const extractMissingCredentials = (
100
95
  ): NotFoundDetail[] => {
101
96
  return getDcqlQueryFailedMatches(queryResult).map(([id]) => {
102
97
  const credential = originalQuery.credentials.find((c) => c.id === id);
103
- if (credential?.format !== "vc+sd-jwt") {
98
+ if (
99
+ credential?.format !== "dc+sd-jwt" &&
100
+ credential?.format !== "vc+sd-jwt"
101
+ ) {
104
102
  throw new Error("Unsupported format"); // TODO [SIW-2082]: support MDOC credentials
105
103
  }
106
104
  return { id, vctValues: credential.meta?.vct_values };
@@ -114,7 +112,6 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = (
114
112
  const credentials = credentialsSdJwt.map(([, credential]) =>
115
113
  mapCredentialToObject(credential)
116
114
  );
117
-
118
115
  try {
119
116
  // Validate the query
120
117
  const parsedQuery = DcqlQuery.parse(query);
@@ -131,11 +128,14 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = (
131
128
  // Build an object vct:credentialJwt to map matched credentials to their JWT
132
129
  const credentialsSdJwtByVct = credentials.reduce(
133
130
  (acc, c, i) => ({ ...acc, [c.vct]: credentialsSdJwt[i]! }),
134
- {} as Record<string, [string /* keyTag */, string /* credential */]>
131
+ {} as Record<string, [CryptoContext, string /* credential */]>
135
132
  );
136
133
 
137
134
  return getDcqlQueryMatches(queryResult).map(([id, match]) => {
138
- if (match.output.credential_format !== "vc+sd-jwt") {
135
+ if (
136
+ match.output.credential_format !== "dc+sd-jwt" &&
137
+ match.output.credential_format !== "vc+sd-jwt"
138
+ ) {
139
139
  throw new Error("Unsupported format"); // TODO [SIW-2082]: support MDOC credentials
140
140
  }
141
141
  const { vct, claims } = match.output;
@@ -147,12 +147,12 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = (
147
147
  required: Boolean(credentialSet.required),
148
148
  }));
149
149
 
150
- const [keyTag, credential] = credentialsSdJwtByVct[vct]!;
150
+ const [cryptoContext, credential] = credentialsSdJwtByVct[vct]!;
151
151
  const requiredDisclosures = Object.values(claims) as Disclosure[];
152
152
  return {
153
153
  id,
154
154
  vct,
155
- keyTag,
155
+ cryptoContext,
156
156
  credential,
157
157
  requiredDisclosures,
158
158
  // When it is a match but no credential_sets are found, the credential is required by default
@@ -185,14 +185,13 @@ export const prepareRemotePresentations: PrepareRemotePresentations = async (
185
185
  const { vp_token } = await prepareVpToken(nonce, clientId, [
186
186
  item.credential,
187
187
  item.requestedClaims,
188
- createCryptoContextFor(item.keyTag),
188
+ item.cryptoContext,
189
189
  ]);
190
190
 
191
191
  return {
192
192
  credentialId: item.id,
193
193
  requestedClaims: item.requestedClaims,
194
194
  vpToken: vp_token,
195
- format: "vc+sd-jwt",
196
195
  };
197
196
  })
198
197
  );
@@ -1,10 +1,10 @@
1
1
  import { InputDescriptor, type LegacyRemotePresentation } from "./types";
2
2
  import { SdJwt4VC, type DisclosureWithEncoded } from "../../sd-jwt/types";
3
3
  import { decode, prepareVpToken } from "../../sd-jwt";
4
- import { createCryptoContextFor } from "../../utils/crypto";
5
4
  import { JSONPath } from "jsonpath-plus";
6
5
  import { CredentialsNotFoundError, MissingDataError } from "./errors";
7
6
  import Ajv from "ajv";
7
+ import type { CryptoContext } from "@pagopa/io-react-native-jwt";
8
8
 
9
9
  const ajv = new Ajv({ allErrors: true });
10
10
  const INDEX_CLAIM_NAME = 1;
@@ -23,13 +23,16 @@ export type EvaluateInputDescriptorSdJwt4VC = (
23
23
 
24
24
  export type EvaluateInputDescriptors = (
25
25
  descriptors: InputDescriptor[],
26
- credentialsSdJwt: [string /* keyTag */, string /* credential */][]
26
+ credentialsSdJwt: [
27
+ CryptoContext /* cryptoContext */,
28
+ string /* credential */,
29
+ ][]
27
30
  ) => Promise<
28
31
  {
29
32
  evaluatedDisclosure: EvaluatedDisclosures;
30
33
  inputDescriptor: InputDescriptor;
31
34
  credential: string;
32
- keyTag: string;
35
+ cryptoContext: CryptoContext;
33
36
  }[]
34
37
  >;
35
38
 
@@ -41,7 +44,7 @@ export type PrepareLegacyRemotePresentations = (
41
44
  requestedClaims: string[];
42
45
  inputDescriptor: InputDescriptor;
43
46
  credential: string;
44
- keyTag: string;
47
+ cryptoContext: CryptoContext;
45
48
  }[],
46
49
  nonce: string,
47
50
  client_id: string
@@ -247,7 +250,7 @@ export const evaluateInputDescriptorForSdJwt4VC: EvaluateInputDescriptorSdJwt4VC
247
250
  };
248
251
 
249
252
  type DecodedCredentialSdJwt = {
250
- keyTag: string;
253
+ cryptoContext: CryptoContext;
251
254
  credential: string;
252
255
  sdJwt: SdJwt4VC;
253
256
  disclosures: DisclosureWithEncoded[];
@@ -264,11 +267,11 @@ export const findCredentialSdJwt = (
264
267
  decodedSdJwtCredentials: DecodedCredentialSdJwt[]
265
268
  ): {
266
269
  matchedEvaluation: EvaluatedDisclosures;
267
- matchedKeyTag: string;
268
270
  matchedCredential: string;
271
+ cryptoContext: CryptoContext;
269
272
  } => {
270
273
  for (const {
271
- keyTag,
274
+ cryptoContext,
272
275
  credential,
273
276
  sdJwt,
274
277
  disclosures,
@@ -282,7 +285,7 @@ export const findCredentialSdJwt = (
282
285
 
283
286
  return {
284
287
  matchedEvaluation: evaluatedDisclosure,
285
- matchedKeyTag: keyTag,
288
+ cryptoContext,
286
289
  matchedCredential: credential,
287
290
  };
288
291
  } catch {
@@ -319,14 +322,14 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
319
322
  ) => {
320
323
  // We need decode SD-JWT credentials for evaluation
321
324
  const decodedSdJwtCredentials =
322
- credentialsSdJwt?.map(([keyTag, credential]) => {
325
+ credentialsSdJwt?.map(([cryptoContext, credential]) => {
323
326
  const { sdJwt, disclosures } = decode(credential);
324
- return { keyTag, credential, sdJwt, disclosures };
327
+ return { cryptoContext, credential, sdJwt, disclosures };
325
328
  }) || [];
326
329
 
327
330
  return Promise.all(
328
331
  inputDescriptors.map(async (descriptor) => {
329
- if (descriptor.format?.["vc+sd-jwt"]) {
332
+ if (descriptor.format?.["dc+sd-jwt"]) {
330
333
  if (!decodedSdJwtCredentials.length) {
331
334
  throw new CredentialsNotFoundError([
332
335
  {
@@ -336,14 +339,14 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
336
339
  ]);
337
340
  }
338
341
 
339
- const { matchedEvaluation, matchedKeyTag, matchedCredential } =
342
+ const { matchedEvaluation, cryptoContext, matchedCredential } =
340
343
  findCredentialSdJwt(descriptor, decodedSdJwtCredentials);
341
344
 
342
345
  return {
343
346
  evaluatedDisclosure: matchedEvaluation,
344
347
  inputDescriptor: descriptor,
345
348
  credential: matchedCredential,
346
- keyTag: matchedKeyTag,
349
+ cryptoContext,
347
350
  };
348
351
  }
349
352
 
@@ -379,18 +382,18 @@ export const prepareLegacyRemotePresentations: PrepareLegacyRemotePresentations
379
382
  credentialAndDescriptors.map(async (item) => {
380
383
  const descriptor = item.inputDescriptor;
381
384
 
382
- if (descriptor.format?.["vc+sd-jwt"]) {
385
+ if (descriptor.format?.["dc+sd-jwt"]) {
383
386
  const { vp_token } = await prepareVpToken(nonce, client_id, [
384
387
  item.credential,
385
388
  item.requestedClaims,
386
- createCryptoContextFor(item.keyTag),
389
+ item.cryptoContext,
387
390
  ]);
388
391
 
389
392
  return {
390
393
  requestedClaims: item.requestedClaims,
391
394
  inputDescriptor: descriptor,
392
395
  vpToken: vp_token,
393
- format: "vc+sd-jwt",
396
+ format: "dc+sd-jwt",
394
397
  };
395
398
  }
396
399
 
@@ -30,7 +30,6 @@ export type LegacyRemotePresentation = {
30
30
  export type RemotePresentation = {
31
31
  requestedClaims: string[];
32
32
  credentialId: string;
33
- format: string;
34
33
  vpToken: string;
35
34
  };
36
35
 
@@ -97,7 +96,7 @@ export const RequestObject = z.object({
97
96
  state: z.string().optional(),
98
97
  nonce: z.string(),
99
98
  response_uri: z.string(),
100
- response_uri_method: z.string().optional(),
99
+ request_uri_method: z.string().optional(),
101
100
  response_type: z.literal("vp_token"),
102
101
  response_mode: z.literal("direct_post.jwt"),
103
102
  client_id: z.string(),
@@ -60,7 +60,6 @@ const { parsedStatusAttestation } =
60
60
  return {
61
61
  statusAttestation: res.statusAttestation,
62
62
  parsedStatusAttestation,
63
- credentialType,
64
63
  };
65
64
  ```
66
65
 
@@ -3,39 +3,14 @@ import { decode, disclose } from "../index";
3
3
 
4
4
  import { encodeBase64, decodeBase64 } from "@pagopa/io-react-native-jwt";
5
5
  import { SdJwt4VC } from "../types";
6
+ import { pid } from "../__mocks__/sd-jwt";
6
7
 
7
- // Examples from https://www.ietf.org/archive/id/draft-terbu-sd-jwt-vc-02.html#name-example-4
8
- // but adapted to adhere to format declared in https://italia.github.io/eudi-wallet-it-docs/versione-corrente/en/pid-eaa-data-model.html#id2
9
- // In short, the token is a Frankenstein composed as follows:
10
- // - the header is taken from the italian specification, with kid and alg valued according to the signing keys
11
- // - disclosures are taken from the SD-JWT-4-VC standard
12
- // - payload is taken from the italian specification, but _sd are compiled with:
13
- // - "address" is used as verification._sd
14
- // - all others disclosures are in claims._sd
15
- const token =
16
- "eyJraWQiOiItRl82VWdhOG4zVmVnalkyVTdZVUhLMXpMb2FELU5QVGM2M1JNSVNuTGF3IiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJfc2QiOlsiMHExRDVKbWF2NnBRYUVoX0pfRmN2X3VOTk1RSWdDeWhRT3hxbFk0bDNxVSIsIktDSi1BVk52ODhkLXhqNnNVSUFPSnhGbmJVaDNySFhES2tJSDFsRnFiUnMiLCJNOWxvOVl4RE5JWHJBcTJxV2VpQ0E0MHpwSl96WWZGZFJfNEFFQUxjUnRVIiwiY3pnalVrMG5xUkNzd1NoQ2hDamRTNkExLXY0N2RfcVRDU0ZJdklIaE1vSSIsIm5HblFyN2NsbTN0ZlRwOHlqTF91SHJEU090elIyUFZiOFM3R2VMZEFxQlEiLCJ4TklWd2xwU3NhWjhDSlNmMGd6NXhfNzVWUldXYzZWMW1scGVqZENycVVzIl0sInN1YiI6IjIxNmY4OTQ2LTllY2ItNDgxOS05MzA5LWMwNzZmMzRhN2UxMSIsIl9zZF9hbGciOiJzaGEtMjU2IiwidmN0IjoiUGVyc29uSWRlbnRpZmljYXRpb25EYXRhIiwiaXNzIjoiaHR0cHM6Ly9wcmUuZWlkLndhbGxldC5pcHpzLml0IiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiUnYzVy1FaUtwdkJUeWs1eVp4dnJldi03TURCNlNselVDQm9fQ1FqamRkVSIsIngiOiIwV294N1F0eVBxQnlnMzVNSF9YeUNjbmQ1TGUtSm0wQVhIbFVnREJBMDNZIiwieSI6ImVFaFZ2ZzFKUHFOZDNEVFNhNG1HREdCbHdZNk5QLUVaYkxiTkZYU1h3SWcifX0sImV4cCI6MTc1MTU0NjU3Niwic3RhdHVzIjp7InN0YXR1c19hdHRlc3RhdGlvbiI6eyJjcmVkZW50aWFsX2hhc2hfYWxnIjoic2hhLTI1NiJ9fX0.qXHA2oqr8trX4fGxpxpUft2GX380TM3pzfo1MYAsDjUC8HsODA-4rdRWAvDe2zYP57x4tJU7eiABkd1Kmln9yQ~WyJrSkRFUDhFYU5URU1CRE9aelp6VDR3IiwidW5pcXVlX2lkIiwiVElOSVQtTFZMREFBODVUNTBHNzAyQiJd~WyJ6SUF5VUZ2UGZJcEUxekJxeEk1aGFRIiwiYmlydGhfZGF0ZSIsIjE5ODUtMTItMTAiXQ~WyJHcjNSM3MyOTBPa1FVbS1ORlR1OTZBIiwidGF4X2lkX2NvZGUiLCJUSU5JVC1MVkxEQUE4NVQ1MEc3MDJCIl0~WyJHeE9SYWxNQWVsZlowZWRGSmpqWVV3IiwiZ2l2ZW5fbmFtZSIsIkFkYSJd~WyJfdlY1UklrbDBJT0VYS290czlrdDF3IiwiZmFtaWx5X25hbWUiLCJMb3ZlbGFjZSJd~WyJDajV0Y2NSNzJKd3J6ZTJUVzRhLXdnIiwiaWF0IiwxNzIwMDEwNTc1XQ";
17
-
18
- const unsigned =
19
- "eyJraWQiOiItRl82VWdhOG4zVmVnalkyVTdZVUhLMXpMb2FELU5QVGM2M1JNSVNuTGF3IiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJfc2QiOlsiMHExRDVKbWF2NnBRYUVoX0pfRmN2X3VOTk1RSWdDeWhRT3hxbFk0bDNxVSIsIktDSi1BVk52ODhkLXhqNnNVSUFPSnhGbmJVaDNySFhES2tJSDFsRnFiUnMiLCJNOWxvOVl4RE5JWHJBcTJxV2VpQ0E0MHpwSl96WWZGZFJfNEFFQUxjUnRVIiwiY3pnalVrMG5xUkNzd1NoQ2hDamRTNkExLXY0N2RfcVRDU0ZJdklIaE1vSSIsIm5HblFyN2NsbTN0ZlRwOHlqTF91SHJEU090elIyUFZiOFM3R2VMZEFxQlEiLCJ4TklWd2xwU3NhWjhDSlNmMGd6NXhfNzVWUldXYzZWMW1scGVqZENycVVzIl0sInN1YiI6IjIxNmY4OTQ2LTllY2ItNDgxOS05MzA5LWMwNzZmMzRhN2UxMSIsIl9zZF9hbGciOiJzaGEtMjU2IiwidmN0IjoiUGVyc29uSWRlbnRpZmljYXRpb25EYXRhIiwiaXNzIjoiaHR0cHM6Ly9wcmUuZWlkLndhbGxldC5pcHpzLml0IiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiUnYzVy1FaUtwdkJUeWs1eVp4dnJldi03TURCNlNselVDQm9fQ1FqamRkVSIsIngiOiIwV294N1F0eVBxQnlnMzVNSF9YeUNjbmQ1TGUtSm0wQVhIbFVnREJBMDNZIiwieSI6ImVFaFZ2ZzFKUHFOZDNEVFNhNG1HREdCbHdZNk5QLUVaYkxiTkZYU1h3SWcifX0sImV4cCI6MTc1MTU0NjU3Niwic3RhdHVzIjp7InN0YXR1c19hdHRlc3RhdGlvbiI6eyJjcmVkZW50aWFsX2hhc2hfYWxnIjoic2hhLTI1NiJ9fX0";
20
-
21
- const signature =
22
- "qXHA2oqr8trX4fGxpxpUft2GX380TM3pzfo1MYAsDjUC8HsODA-4rdRWAvDe2zYP57x4tJU7eiABkd1Kmln9yQ";
23
-
24
- const signed = `${unsigned}.${signature}`;
25
-
26
- const tokenizedDisclosures = [
27
- "WyJrSkRFUDhFYU5URU1CRE9aelp6VDR3IiwidW5pcXVlX2lkIiwiVElOSVQtTFZMREFBODVUNTBHNzAyQiJd",
28
- "WyJ6SUF5VUZ2UGZJcEUxekJxeEk1aGFRIiwiYmlydGhfZGF0ZSIsIjE5ODUtMTItMTAiXQ",
29
- "WyJHcjNSM3MyOTBPa1FVbS1ORlR1OTZBIiwidGF4X2lkX2NvZGUiLCJUSU5JVC1MVkxEQUE4NVQ1MEc3MDJCIl0",
30
- "WyJHeE9SYWxNQWVsZlowZWRGSmpqWVV3IiwiZ2l2ZW5fbmFtZSIsIkFkYSJd",
31
- "WyJfdlY1UklrbDBJT0VYS290czlrdDF3IiwiZmFtaWx5X25hbWUiLCJMb3ZlbGFjZSJd",
32
- "WyJDajV0Y2NSNzJKd3J6ZTJUVzRhLXdnIiwiaWF0IiwxNzIwMDEwNTc1XQ",
33
- ];
8
+ const { token, signed, tokenizedDisclosures } = pid;
34
9
 
35
10
  const sdJwt = {
36
11
  header: {
37
12
  kid: "-F_6Uga8n3VegjY2U7YUHK1zLoaD-NPTc63RMISnLaw",
38
- typ: "vc+sd-jwt",
13
+ typ: "dc+sd-jwt",
39
14
  alg: "ES256",
40
15
  },
41
16
  payload: {
@@ -50,7 +25,11 @@ const sdJwt = {
50
25
  sub: "216f8946-9ecb-4819-9309-c076f34a7e11",
51
26
  _sd_alg: "sha-256",
52
27
  vct: "PersonIdentificationData",
28
+ "vct#integrity":
29
+ "13e25888ac7b8a3a6d61440da787fccc81654e61085732bcacd89b36aec32675",
53
30
  iss: "https://pre.eid.wallet.ipzs.it",
31
+ issuing_country: "IT",
32
+ issuing_authority: "Istituto Poligrafico e Zecca dello Stato",
54
33
  cnf: {
55
34
  jwk: {
56
35
  kty: "EC",
@@ -62,7 +41,7 @@ const sdJwt = {
62
41
  },
63
42
  exp: 1751546576,
64
43
  status: {
65
- status_attestation: {
44
+ status_assertion: {
66
45
  credential_hash_alg: "sha-256",
67
46
  },
68
47
  },
@@ -5,7 +5,7 @@ describe("SdJwt4VC", () => {
5
5
  // example provided at https://italia.github.io/eidas-it-wallet-docs/en/pid-data-model.html
6
6
  const token = {
7
7
  header: {
8
- typ: "vc+sd-jwt",
8
+ typ: "dc+sd-jwt",
9
9
  alg: "RS512",
10
10
  kid: "dB67gL7ck3TFiIAf7N6_7SHvqk0MDYMEQcoGGlkUAAw",
11
11
  },
@@ -21,7 +21,11 @@ describe("SdJwt4VC", () => {
21
21
  sub: "216f8946-9ecb-4819-9309-c076f34a7e11",
22
22
  _sd_alg: "sha-256",
23
23
  vct: "PersonIdentificationData",
24
+ "vct#integrity":
25
+ "13e25888ac7b8a3a6d61440da787fccc81654e61085732bcacd89b36aec32675",
24
26
  iss: "https://pidprovider.example.com",
27
+ issuing_country: "IT",
28
+ issuing_authority: "Istituto Poligrafico e Zecca dello Stato",
25
29
  cnf: {
26
30
  jwk: {
27
31
  kty: "EC",
@@ -33,7 +37,7 @@ describe("SdJwt4VC", () => {
33
37
  },
34
38
  exp: 1751107255,
35
39
  status: {
36
- status_attestation: {
40
+ status_assertion: {
37
41
  credential_hash_alg: "sha-256",
38
42
  },
39
43
  },