@pagopa/io-react-native-wallet 1.1.2 → 1.2.2

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 (99) hide show
  1. package/lib/commonjs/credential/presentation/01-start-flow.js +7 -5
  2. package/lib/commonjs/credential/presentation/01-start-flow.js.map +1 -1
  3. package/lib/commonjs/credential/presentation/03-get-request-object.js +47 -0
  4. package/lib/commonjs/credential/presentation/03-get-request-object.js.map +1 -0
  5. package/lib/commonjs/credential/presentation/04-retrieve-rp-jwks.js +82 -0
  6. package/lib/commonjs/credential/presentation/04-retrieve-rp-jwks.js.map +1 -0
  7. package/lib/commonjs/credential/presentation/05-verify-request-object.js +35 -0
  8. package/lib/commonjs/credential/presentation/05-verify-request-object.js.map +1 -0
  9. package/lib/commonjs/credential/presentation/06-fetch-presentation-definition.js +63 -0
  10. package/lib/commonjs/credential/presentation/06-fetch-presentation-definition.js.map +1 -0
  11. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +169 -0
  12. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -0
  13. package/lib/commonjs/credential/presentation/08-send-authorization-response.js +202 -0
  14. package/lib/commonjs/credential/presentation/08-send-authorization-response.js.map +1 -0
  15. package/lib/commonjs/credential/presentation/README.md +43 -4
  16. package/lib/commonjs/credential/presentation/errors.js +52 -1
  17. package/lib/commonjs/credential/presentation/errors.js.map +1 -1
  18. package/lib/commonjs/credential/presentation/index.js +27 -6
  19. package/lib/commonjs/credential/presentation/index.js.map +1 -1
  20. package/lib/commonjs/credential/presentation/types.js +69 -4
  21. package/lib/commonjs/credential/presentation/types.js.map +1 -1
  22. package/lib/commonjs/entity/trust/types.js +4 -1
  23. package/lib/commonjs/entity/trust/types.js.map +1 -1
  24. package/lib/module/credential/presentation/01-start-flow.js +8 -6
  25. package/lib/module/credential/presentation/01-start-flow.js.map +1 -1
  26. package/lib/module/credential/presentation/03-get-request-object.js +39 -0
  27. package/lib/module/credential/presentation/03-get-request-object.js.map +1 -0
  28. package/lib/module/credential/presentation/04-retrieve-rp-jwks.js +75 -0
  29. package/lib/module/credential/presentation/04-retrieve-rp-jwks.js.map +1 -0
  30. package/lib/module/credential/presentation/05-verify-request-object.js +28 -0
  31. package/lib/module/credential/presentation/05-verify-request-object.js.map +1 -0
  32. package/lib/module/credential/presentation/06-fetch-presentation-definition.js +56 -0
  33. package/lib/module/credential/presentation/06-fetch-presentation-definition.js.map +1 -0
  34. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +161 -0
  35. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -0
  36. package/lib/module/credential/presentation/08-send-authorization-response.js +188 -0
  37. package/lib/module/credential/presentation/08-send-authorization-response.js.map +1 -0
  38. package/lib/module/credential/presentation/README.md +43 -4
  39. package/lib/module/credential/presentation/errors.js +48 -0
  40. package/lib/module/credential/presentation/errors.js.map +1 -1
  41. package/lib/module/credential/presentation/index.js +7 -4
  42. package/lib/module/credential/presentation/index.js.map +1 -1
  43. package/lib/module/credential/presentation/types.js +67 -3
  44. package/lib/module/credential/presentation/types.js.map +1 -1
  45. package/lib/module/entity/trust/types.js +4 -1
  46. package/lib/module/entity/trust/types.js.map +1 -1
  47. package/lib/typescript/credential/presentation/01-start-flow.d.ts.map +1 -1
  48. package/lib/typescript/credential/presentation/{04-get-request-object.d.ts → 03-get-request-object.d.ts} +3 -5
  49. package/lib/typescript/credential/presentation/03-get-request-object.d.ts.map +1 -0
  50. package/lib/typescript/credential/presentation/{03-retrieve-jwks.d.ts → 04-retrieve-rp-jwks.d.ts} +5 -4
  51. package/lib/typescript/credential/presentation/04-retrieve-rp-jwks.d.ts.map +1 -0
  52. package/lib/typescript/credential/presentation/05-verify-request-object.d.ts +8 -0
  53. package/lib/typescript/credential/presentation/05-verify-request-object.d.ts.map +1 -0
  54. package/lib/typescript/credential/presentation/06-fetch-presentation-definition.d.ts +26 -0
  55. package/lib/typescript/credential/presentation/06-fetch-presentation-definition.d.ts.map +1 -0
  56. package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts +27 -0
  57. package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -0
  58. package/lib/typescript/credential/presentation/08-send-authorization-response.d.ts +99 -0
  59. package/lib/typescript/credential/presentation/08-send-authorization-response.d.ts.map +1 -0
  60. package/lib/typescript/credential/presentation/errors.d.ts +33 -0
  61. package/lib/typescript/credential/presentation/errors.d.ts.map +1 -1
  62. package/lib/typescript/credential/presentation/index.d.ts +8 -5
  63. package/lib/typescript/credential/presentation/index.d.ts.map +1 -1
  64. package/lib/typescript/credential/presentation/types.d.ts +612 -9
  65. package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
  66. package/lib/typescript/entity/trust/index.d.ts +152 -0
  67. package/lib/typescript/entity/trust/index.d.ts.map +1 -1
  68. package/lib/typescript/entity/trust/types.d.ts +2088 -0
  69. package/lib/typescript/entity/trust/types.d.ts.map +1 -1
  70. package/package.json +5 -1
  71. package/src/credential/presentation/01-start-flow.ts +10 -6
  72. package/src/credential/presentation/{04-get-request-object.ts → 03-get-request-object.ts} +6 -51
  73. package/src/credential/presentation/{03-retrieve-jwks.ts → 04-retrieve-rp-jwks.ts} +39 -24
  74. package/src/credential/presentation/05-verify-request-object.ts +35 -0
  75. package/src/credential/presentation/06-fetch-presentation-definition.ts +78 -0
  76. package/src/credential/presentation/07-evaluate-input-descriptor.ts +204 -0
  77. package/src/credential/presentation/08-send-authorization-response.ts +251 -0
  78. package/src/credential/presentation/README.md +43 -4
  79. package/src/credential/presentation/errors.ts +48 -0
  80. package/src/credential/presentation/index.ts +27 -9
  81. package/src/credential/presentation/types.ts +59 -3
  82. package/src/entity/trust/types.ts +3 -0
  83. package/lib/commonjs/credential/presentation/03-retrieve-jwks.js +0 -68
  84. package/lib/commonjs/credential/presentation/03-retrieve-jwks.js.map +0 -1
  85. package/lib/commonjs/credential/presentation/04-get-request-object.js +0 -82
  86. package/lib/commonjs/credential/presentation/04-get-request-object.js.map +0 -1
  87. package/lib/commonjs/credential/presentation/05-send-authorization-response.js +0 -139
  88. package/lib/commonjs/credential/presentation/05-send-authorization-response.js.map +0 -1
  89. package/lib/module/credential/presentation/03-retrieve-jwks.js +0 -61
  90. package/lib/module/credential/presentation/03-retrieve-jwks.js.map +0 -1
  91. package/lib/module/credential/presentation/04-get-request-object.js +0 -74
  92. package/lib/module/credential/presentation/04-get-request-object.js.map +0 -1
  93. package/lib/module/credential/presentation/05-send-authorization-response.js +0 -128
  94. package/lib/module/credential/presentation/05-send-authorization-response.js.map +0 -1
  95. package/lib/typescript/credential/presentation/03-retrieve-jwks.d.ts.map +0 -1
  96. package/lib/typescript/credential/presentation/04-get-request-object.d.ts.map +0 -1
  97. package/lib/typescript/credential/presentation/05-send-authorization-response.d.ts +0 -34
  98. package/lib/typescript/credential/presentation/05-send-authorization-response.d.ts.map +0 -1
  99. package/src/credential/presentation/05-send-authorization-response.ts +0 -168
@@ -0,0 +1,251 @@
1
+ import {
2
+ EncryptJwe,
3
+ SignJWT,
4
+ sha256ToBase64,
5
+ } from "@pagopa/io-react-native-jwt";
6
+ import uuid from "react-native-uuid";
7
+ import type { FetchJwks } from "./04-retrieve-rp-jwks";
8
+ import type { VerifyRequestObjectSignature } from "./05-verify-request-object";
9
+ import type { JWK } from "@pagopa/io-react-native-jwt/lib/typescript/types";
10
+ import { NoSuitableKeysFoundInEntityConfiguration } from "./errors";
11
+ import { hasStatusOrThrow, type Out } from "../../utils/misc";
12
+ import { disclose } from "../../sd-jwt";
13
+ import { PresentationDefinition, type Presentation } from "./types";
14
+ import * as z from "zod";
15
+
16
+ export type AuthorizationResponse = z.infer<typeof AuthorizationResponse>;
17
+ export const AuthorizationResponse = z.object({
18
+ status: z.string().optional(),
19
+ response_code: z
20
+ .string() /**
21
+ FIXME: [SIW-627] we expect this value from every RP implementation
22
+ Actually some RP does not return the value
23
+ We make it optional to not break the flow.
24
+ */
25
+ .optional(),
26
+ redirect_uri: z.string().optional(),
27
+ });
28
+
29
+ /**
30
+ * Selects an RSA public key (with `use = enc` and `kty = RSA`) from the set of JWK keys
31
+ * offered by the Relying Party (RP) for encryption.
32
+ *
33
+ * @param rpJwkKeys - The array of JWKs retrieved from the RP entity configuration.
34
+ * @returns The first suitable RSA public key found in the list.
35
+ * @throws {NoSuitableKeysFoundInEntityConfiguration} If no suitable RSA encryption key is found.
36
+ */
37
+ export const chooseRSAPublicKeyToEncrypt = (
38
+ rpJwkKeys: Out<FetchJwks>["keys"]
39
+ ): JWK => {
40
+ const [rsaEncKey] = rpJwkKeys.filter(
41
+ (jwk) => jwk.use === "enc" && jwk.kty === "RSA"
42
+ );
43
+
44
+ if (rsaEncKey) {
45
+ return rsaEncKey;
46
+ }
47
+
48
+ // No suitable key found
49
+ throw new NoSuitableKeysFoundInEntityConfiguration(
50
+ "No suitable RSA public key found for encryption."
51
+ );
52
+ };
53
+
54
+ /**
55
+ * Prepares a Verified Presentation (VP) token to be sent as part of an
56
+ * authorization response in an OpenID 4 Verifiable Presentations flow.
57
+ *
58
+ * @param requestObject - The request object containing the nonce, response URI, and other necessary info.
59
+ * @param presentationTuple - A tuple containing a verifiable credential, the claims to disclose,
60
+ * and a cryptographic context for signing.
61
+ * @returns An object containing the signed VP token (`vp_token`) and a `presentation_submission` object.
62
+ * @param presentationDefinition - Definition outlining presentation requirements.
63
+ * @param presentationTuple - Tuple containing:
64
+ * - A verifiable credential.
65
+ * - Claims that should be disclosed.
66
+ * - Cryptographic context for signing.
67
+ * @returns An object with:
68
+ * - `vp_token`: The signed VP token.
69
+ * - `presentation_submission`: Object mapping disclosed credentials to the request.
70
+ *
71
+ * @remarks
72
+ * 1. The `disclose()` function is used to produce a token with only the requested claims.
73
+ * 2. A new JWT is then signed, including the VP, `jti`, `iss`, `nonce`, audience, and expiration.
74
+ * 3. The `presentation_submission` object follows the OpenID 4 VP specification for describing
75
+ * how the disclosed credentials map to the request.
76
+ *
77
+ * @todo [SIW-353] Support multiple verifiable credentials in a single request.
78
+ */
79
+ export const prepareVpToken = async (
80
+ requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
81
+ presentationDefinition: PresentationDefinition,
82
+ [verifiableCredential, requestedClaims, cryptoContext]: Presentation
83
+ ): Promise<{
84
+ vp_token: string;
85
+ presentation_submission: Record<string, unknown>;
86
+ }> => {
87
+ // Produce a VP token with only requested claims from the verifiable credential
88
+ const { token: vp } = await disclose(verifiableCredential, requestedClaims);
89
+
90
+ // <Issuer-signed JWT>~<Disclosure 1>~<Disclosure N>~
91
+ const sd_hash = await sha256ToBase64(`${vp}~`);
92
+
93
+ const kbJwt = await new SignJWT(cryptoContext)
94
+ .setProtectedHeader({
95
+ typ: "kb+jwt",
96
+ alg: "ES256",
97
+ })
98
+ .setPayload({
99
+ sd_hash,
100
+ nonce: requestObject.nonce,
101
+ })
102
+ .setAudience(requestObject.client_id)
103
+ .setIssuedAt()
104
+ .sign();
105
+
106
+ // <Issuer-signed JWT>~<Disclosure 1>~...~<Disclosure N>~<KB-JWT>
107
+ const vp_token = [vp, kbJwt].join("~");
108
+
109
+ // Determine the descriptor ID to use for mapping. Fallback to first input descriptor ID if not specified
110
+ // We support only one credential for now, so we get first input_descriptor and create just one descriptor_map
111
+ const presentation_submission = {
112
+ id: uuid.v4(),
113
+ definition_id: presentationDefinition.id,
114
+ descriptor_map: [
115
+ {
116
+ id: presentationDefinition?.input_descriptors[0]?.id,
117
+ path: `$`,
118
+ format: "vc+sd-jwt",
119
+ },
120
+ ],
121
+ };
122
+
123
+ return { vp_token, presentation_submission };
124
+ };
125
+
126
+ /**
127
+ * Builds a URL-encoded form body for a direct POST response without encryption.
128
+ *
129
+ * @param requestObject - Contains state, nonce, and other relevant info.
130
+ * @param vpToken - The signed VP token to include.
131
+ * @param presentationSubmission - Object mapping credential disclosures.
132
+ * @returns A URL-encoded string suitable for an `application/x-www-form-urlencoded` POST body.
133
+ */
134
+ export const buildDirectPostBody = async (
135
+ requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
136
+ vpToken: string,
137
+ presentationSubmission: Record<string, unknown>
138
+ ): Promise<string> => {
139
+ const formUrlEncodedBody = new URLSearchParams({
140
+ state: requestObject.state,
141
+ presentation_submission: JSON.stringify(presentationSubmission),
142
+ vp_token: vpToken,
143
+ });
144
+
145
+ return formUrlEncodedBody.toString();
146
+ };
147
+
148
+ /**
149
+ * Builds a URL-encoded form body for a direct POST response using JWT encryption.
150
+ *
151
+ * @param jwkKeys - Array of JWKs from the Relying Party for encryption.
152
+ * @param requestObject - Contains state, nonce, and other relevant info.
153
+ * @param vpToken - The signed VP token to encrypt.
154
+ * @param presentationSubmission - Object mapping credential disclosures.
155
+ * @returns A URL-encoded string for an `application/x-www-form-urlencoded` POST body,
156
+ * where `response` contains the encrypted JWE.
157
+ */
158
+ export const buildDirectPostJwtBody = async (
159
+ jwkKeys: Out<FetchJwks>["keys"],
160
+ requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
161
+ vpToken: string,
162
+ presentationSubmission: Record<string, unknown>
163
+ ): Promise<string> => {
164
+ // Prepare the authorization response payload to be encrypted
165
+ const authzResponsePayload = JSON.stringify({
166
+ state: requestObject.state,
167
+ presentation_submission: presentationSubmission,
168
+ vp_token: vpToken,
169
+ });
170
+
171
+ // Choose a suitable RSA public key for encryption
172
+ const rsaPublicJwk = chooseRSAPublicKeyToEncrypt(jwkKeys);
173
+
174
+ // Encrypt the authorization payload
175
+ const encryptedResponse = await new EncryptJwe(authzResponsePayload, {
176
+ alg: "RSA-OAEP-256",
177
+ enc: "A256CBC-HS512",
178
+ kid: rsaPublicJwk.kid,
179
+ }).encrypt(rsaPublicJwk);
180
+
181
+ // Build the x-www-form-urlencoded form body
182
+ const formBody = new URLSearchParams({ response: encryptedResponse });
183
+ return formBody.toString();
184
+ };
185
+
186
+ /**
187
+ * Type definition for the function that sends the authorization response
188
+ * to the Relying Party, completing the presentation flow.
189
+ */
190
+ export type SendAuthorizationResponse = (
191
+ requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
192
+ presentationDefinition: PresentationDefinition,
193
+ jwkKeys: Out<FetchJwks>["keys"],
194
+ presentation: Presentation, // TODO: [SIW-353] support multiple presentations
195
+ context: {
196
+ appFetch?: GlobalFetch["fetch"];
197
+ }
198
+ ) => Promise<AuthorizationResponse>;
199
+
200
+ /**
201
+ * Sends the authorization response to the Relying Party (RP) using the specified `response_mode`.
202
+ * This function completes the presentation flow in an OpenID 4 Verifiable Presentations scenario.
203
+ *
204
+ * @param requestObject - The request details, including presentation requirements.
205
+ * @param presentationDefinition - The definition of the expected presentation.
206
+ * @param jwkKeys - Array of JWKs from the Relying Party for optional encryption.
207
+ * @param presentation - Tuple with verifiable credential, claims, and crypto context.
208
+ * @param context - Contains optional custom fetch implementation.
209
+ * @returns Parsed and validated authorization response from the Relying Party.
210
+ */
211
+ export const sendAuthorizationResponse: SendAuthorizationResponse = async (
212
+ requestObject,
213
+ presentationDefinition,
214
+ jwkKeys,
215
+ presentation,
216
+ { appFetch = fetch }
217
+ ): Promise<AuthorizationResponse> => {
218
+ // 1. Create the VP token and associated submission mapping
219
+ const { vp_token, presentation_submission } = await prepareVpToken(
220
+ requestObject,
221
+ presentationDefinition,
222
+ presentation
223
+ );
224
+
225
+ // 2. Choose the appropriate request body builder based on response mode
226
+ const requestBody =
227
+ requestObject.response_mode === "direct_post.jwt"
228
+ ? await buildDirectPostJwtBody(
229
+ jwkKeys,
230
+ requestObject,
231
+ vp_token,
232
+ presentation_submission
233
+ )
234
+ : await buildDirectPostBody(
235
+ requestObject,
236
+ vp_token,
237
+ presentation_submission
238
+ );
239
+
240
+ // 3. Send the authorization response via HTTP POST and validate the response
241
+ return await appFetch(requestObject.response_uri, {
242
+ method: "POST",
243
+ headers: {
244
+ "Content-Type": "application/x-www-form-urlencoded",
245
+ },
246
+ body: requestBody,
247
+ })
248
+ .then(hasStatusOrThrow(200))
249
+ .then((res) => res.json())
250
+ .then(AuthorizationResponse.parse);
251
+ };
@@ -60,15 +60,54 @@ const { requestURI, clientId } = Credential.Presentation.startFlowFromQR(qrcode)
60
60
  // If use trust federation: Evaluate issuer trust
61
61
  const { rpConf } = await Credential.Presentation.evaluateRelyingPartyTrust(clientId);
62
62
 
63
+ const { requestObjectEncodedJwt } =
64
+ await Credential.Presentation.getRequestObject(requestURI, {
65
+ wiaCryptoContext: wiaCryptoContext,
66
+ appFetch: appFetch,
67
+ walletInstanceAttestation: walletInstanceAttestation,
68
+ });
69
+
70
+ // Retrieve RP JWK
63
71
  // If use trust federation: Fetch Jwks from rpConf
64
72
  const jwks = await Credential.Presentation.fetchJwksFromConfig(rpConf);
65
73
 
66
- // If not use trust: Fetch Jwks from well-know
67
- const jwks = await Credential.Presentation.fetchJwksFromUri(
68
- requestURI,
69
- appFetch,
74
+ // If not use trust: Fetch Jwks from request object
75
+ const jwks = await Credential.Presentation.fetchJwksFromRequestObject(
76
+ requestObjectEncodedJwt,
77
+ { context: { appFetch } }
70
78
  );
71
79
 
80
+ // Verify signature Request Object
81
+ const { requestObject } =
82
+ await Credential.Presentation.verifyRequestObjectSignature(
83
+ requestObjectEncodedJwt,
84
+ jwks.keys
85
+ );
86
+
87
+
88
+ const { presentationDefinition } = await Credential.Presentation.fetchPresentDefinition(
89
+ requestObject,
90
+ {
91
+ appFetch: appFetch,
92
+ },
93
+ rpConf // If trust federation is used
94
+ );
95
+
96
+ // For each credential, find it and evaluate input descriptor and disclosures
97
+ const { requiredDisclosures } = Credential.Presentation.evaluateInputDescriptionForSdJwt4VC(
98
+ inputDescriptor,
99
+ credential.payload,
100
+ disclosures
101
+ );
102
+
103
+ // After confirm disclosures in app
104
+ const authResponse = Credential.Presentation.sendAuthorizationResponse(
105
+ requestObject,
106
+ presentationDefinition,
107
+ jwks,
108
+ [credential, disclosuresRequested, { appFetch: appFetch }]
109
+ );
110
+
72
111
 
73
112
  ```
74
113
 
@@ -39,3 +39,51 @@ export class NoSuitableKeysFoundInEntityConfiguration extends IoWalletError {
39
39
  super(message);
40
40
  }
41
41
  }
42
+
43
+ /**
44
+ * When a QR code is not valid.
45
+ *
46
+ */
47
+ export class InvalidQRCodeError extends IoWalletError {
48
+ code = "ERR_INVALID_QR_CODE";
49
+
50
+ /**
51
+ * @param detail A description of why the QR code is considered invalid.
52
+ */
53
+ constructor(detail: string) {
54
+ const message = `QR code is not valid: ${detail}.`;
55
+ super(message);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * When the entity is unverified because the Relying Party is not trusted.
61
+ *
62
+ */
63
+ export class UnverifiedEntityError extends IoWalletError {
64
+ code = "ERR_UNVERIFIED_RP_ENTITY";
65
+
66
+ /**
67
+ * @param reason A description of why the entity cannot be verified.
68
+ */
69
+ constructor(reason: string) {
70
+ const message = `Unverified entity: ${reason}.`;
71
+ super(message);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * When some required data is missing to continue because certain attributes are not contained inside the wallet.
77
+ *
78
+ */
79
+ export class MissingDataError extends IoWalletError {
80
+ code = "ERR_MISSING_DATA";
81
+
82
+ /**
83
+ * @param missingAttributes An array or description of the attributes that are missing.
84
+ */
85
+ constructor(missingAttributes: string) {
86
+ const message = `Some required data is missing: ${missingAttributes}.`;
87
+ super(message);
88
+ }
89
+ }
@@ -4,33 +4,51 @@ import {
4
4
  type EvaluateRelyingPartyTrust,
5
5
  } from "./02-evaluate-rp-trust";
6
6
  import {
7
- fetchJwksFromUri,
7
+ getRequestObject,
8
+ type GetRequestObject,
9
+ } from "./03-get-request-object";
10
+ import {
11
+ fetchJwksFromRequestObject,
8
12
  fetchJwksFromConfig,
9
13
  type FetchJwks,
10
- } from "./03-retrieve-jwks";
14
+ } from "./04-retrieve-rp-jwks";
11
15
  import {
12
- getRequestObject,
13
- type GetRequestObject,
14
- } from "./04-get-request-object";
16
+ verifyRequestObjectSignature,
17
+ type VerifyRequestObjectSignature,
18
+ } from "./05-verify-request-object";
19
+ import {
20
+ fetchPresentDefinition,
21
+ type FetchPresentationDefinition,
22
+ } from "./06-fetch-presentation-definition";
23
+ import {
24
+ evaluateInputDescriptorForSdJwt4VC,
25
+ type EvaluateInputDescriptorSdJwt4VC,
26
+ } from "./07-evaluate-input-descriptor";
15
27
  import {
16
28
  sendAuthorizationResponse,
17
29
  type SendAuthorizationResponse,
18
- } from "./05-send-authorization-response";
30
+ } from "./08-send-authorization-response";
19
31
  import * as Errors from "./errors";
20
32
 
21
33
  export {
22
34
  startFlowFromQR,
23
35
  evaluateRelyingPartyTrust,
24
- fetchJwksFromUri,
25
- fetchJwksFromConfig,
26
36
  getRequestObject,
37
+ fetchJwksFromRequestObject,
38
+ fetchJwksFromConfig,
39
+ verifyRequestObjectSignature,
40
+ fetchPresentDefinition,
41
+ evaluateInputDescriptorForSdJwt4VC,
27
42
  sendAuthorizationResponse,
28
43
  Errors,
29
44
  };
30
45
  export type {
31
46
  StartFlow,
32
47
  EvaluateRelyingPartyTrust,
33
- FetchJwks,
34
48
  GetRequestObject,
49
+ FetchJwks,
50
+ VerifyRequestObjectSignature,
51
+ FetchPresentationDefinition,
52
+ EvaluateInputDescriptorSdJwt4VC,
35
53
  SendAuthorizationResponse,
36
54
  };
@@ -11,17 +11,73 @@ export type Presentation = [
11
11
  /* the context for the key associated to the credential */ CryptoContext
12
12
  ];
13
13
 
14
+ const Fields = z.object({
15
+ path: z.array(z.string().min(1)), // Array of JSONPath string expressions
16
+ id: z.string().optional(), // Unique string ID
17
+ purpose: z.string().optional(), // Purpose of the field
18
+ name: z.string().optional(), // Human-friendly name
19
+ filter: z.any().optional(), // JSON Schema descriptor for filtering
20
+ optional: z.boolean().optional(), // Boolean indicating if the field is optional
21
+ intent_to_retain: z.boolean().optional(), // Boolean indicating that the Verifier intends to retain the Claim's data being requested
22
+ });
23
+
24
+ // Define the Constraints Object Schema
25
+ const Constraints = z.object({
26
+ fields: z.array(Fields).optional(), // Array of Field Objects
27
+ limit_disclosure: z.enum(["required", "preferred"]).optional(), // Limit disclosure property
28
+ });
29
+
30
+ // Define the Input Descriptor Object Schema
31
+ export type InputDescriptor = z.infer<typeof InputDescriptor>;
32
+ export const InputDescriptor = z.object({
33
+ id: z.string().min(1), // Mandatory unique string ID
34
+ name: z.string().optional(), // Human-friendly name
35
+ purpose: z.string().optional(), // Purpose of the schema
36
+ format: z.record(z.string(), z.any()).optional(), // Object with Claim Format Designations
37
+ constraints: Constraints, // Constraints Object (mandatory)
38
+ group: z.string().optional(), // Match one of the grouping strings listed in the "from" values of a Submission Requirement Rule
39
+ });
40
+
41
+ const SubmissionRequirement = z.object({
42
+ name: z.string().optional(),
43
+ purpose: z.string().optional(),
44
+ rule: z.string(), // "all": all group's rules must be present, or "pick": at least group's "count" rules must be present
45
+ from: z.string().optional(), // MUST contain either a "from" or "from_nested" property
46
+ from_nested: z
47
+ .array(
48
+ z.object({
49
+ name: z.string().optional(),
50
+ purpose: z.string().optional(),
51
+ rule: z.string(),
52
+ from: z.string(),
53
+ })
54
+ )
55
+ .optional(),
56
+ count: z.number().optional(),
57
+ //"count", "min", and "max" may be present with a "pick" rule
58
+ });
59
+
60
+ export type PresentationDefinition = z.infer<typeof PresentationDefinition>;
61
+ export const PresentationDefinition = z.object({
62
+ id: z.string(),
63
+ name: z.string().optional(),
64
+ purpose: z.string().optional(),
65
+ input_descriptors: z.array(InputDescriptor),
66
+ submission_requirements: z.array(SubmissionRequirement).optional(),
67
+ });
68
+
14
69
  export type RequestObject = z.infer<typeof RequestObject>;
15
70
  export const RequestObject = z.object({
16
71
  iss: z.string().optional(), //optional by RFC 7519, mandatory for Potential
17
- iat: UnixTime,
72
+ iat: UnixTime.optional(),
18
73
  exp: UnixTime.optional(),
19
74
  state: z.string(),
20
75
  nonce: z.string(),
21
76
  response_uri: z.string(),
22
77
  response_type: z.literal("vp_token"),
23
- response_mode: z.literal("direct_post.jwt"),
78
+ response_mode: z.enum(["direct_post.jwt", "direct_post"]),
24
79
  client_id: z.string(),
25
80
  client_id_scheme: z.string(), // previous z.literal("entity_id"),
26
- scope: z.string(),
81
+ scope: z.string().optional(),
82
+ presentation_definition: PresentationDefinition.optional(),
27
83
  });
@@ -1,6 +1,7 @@
1
1
  import { UnixTime } from "../../sd-jwt/types";
2
2
  import { JWK } from "../../utils/jwk";
3
3
  import * as z from "zod";
4
+ import { PresentationDefinition } from "../../credential/presentation/types";
4
5
 
5
6
  export const TrustMark = z.object({ id: z.string(), trust_mark: z.string() });
6
7
  export type TrustMark = z.infer<typeof TrustMark>;
@@ -11,6 +12,8 @@ const RelyingPartyMetadata = z.object({
11
12
  client_name: z.string().optional(),
12
13
  jwks: z.object({ keys: z.array(JWK) }),
13
14
  contacts: z.array(z.string()).optional(),
15
+ presentation_definition: PresentationDefinition.optional(),
16
+ presentation_definition_uri: z.string().optional(),
14
17
  });
15
18
  //.passthrough();
16
19
 
@@ -1,68 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.fetchJwksFromUri = exports.fetchJwksFromConfig = void 0;
7
- var _jwk = require("../../utils/jwk");
8
- var _misc = require("../../utils/misc");
9
- var _types = require("../../entity/trust/types");
10
- /**
11
- * Defines the signature for a function that retrieves JSON Web Key Sets (JWKS) from a client.
12
- *
13
- * @template T - The tuple type representing the function arguments.
14
- * @param args - The arguments passed to the function.
15
- * @returns A promise resolving to an object containing an array of JWKs.
16
- */
17
-
18
- /**
19
- * Retrieves the JSON Web Key Set (JWKS) from the specified client's well-known endpoint.
20
- *
21
- * @param clientUrl - The base URL of the client entity from which to retrieve the JWKS.
22
- * @param options - Optional context containing a custom fetch implementation.
23
- * @param options.context - Optional context object.
24
- * @param options.context.appFetch - Optional custom fetch function to use instead of the global `fetch`.
25
- * @returns A promise resolving to an object containing an array of JWKs.
26
- * @throws Will throw an error if the JWKS retrieval fails.
27
- */
28
- const fetchJwksFromUri = async function (clientUrl) {
29
- let {
30
- context = {}
31
- } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
32
- const {
33
- appFetch = fetch
34
- } = context;
35
- const wellKnownUrl = new URL("/.well-known/jar-issuer/jwk", clientUrl).toString();
36
-
37
- // Fetches the JWKS from a specific endpoint of the entity's well-known configuration
38
- const jwks = await appFetch(wellKnownUrl, {
39
- method: "GET"
40
- }).then((0, _misc.hasStatusOrThrow)(200)).then(raw => raw.json()).then(json => _jwk.JWKS.parse(json));
41
- return {
42
- keys: jwks.keys
43
- };
44
- };
45
-
46
- /**
47
- * Retrieves the JSON Web Key Set (JWKS) from a Relying Party's entity configuration.
48
- *
49
- * @param rpConfig - The configuration object of the Relying Party entity.
50
- * @returns An object containing an array of JWKs.
51
- * @throws Will throw an error if the configuration is invalid or if JWKS is not found.
52
- */
53
- exports.fetchJwksFromUri = fetchJwksFromUri;
54
- const fetchJwksFromConfig = async rpConfig => {
55
- const parsedConfig = _types.RelyingPartyEntityConfiguration.safeParse(rpConfig);
56
- if (!parsedConfig.success) {
57
- throw new Error("Invalid Relying Party configuration.");
58
- }
59
- const jwks = parsedConfig.data.payload.metadata.wallet_relying_party.jwks;
60
- if (!jwks || !Array.isArray(jwks.keys)) {
61
- throw new Error("JWKS not found in Relying Party configuration.");
62
- }
63
- return {
64
- keys: jwks.keys
65
- };
66
- };
67
- exports.fetchJwksFromConfig = fetchJwksFromConfig;
68
- //# sourceMappingURL=03-retrieve-jwks.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_jwk","require","_misc","_types","fetchJwksFromUri","clientUrl","context","arguments","length","undefined","appFetch","fetch","wellKnownUrl","URL","toString","jwks","method","then","hasStatusOrThrow","raw","json","JWKS","parse","keys","exports","fetchJwksFromConfig","rpConfig","parsedConfig","RelyingPartyEntityConfiguration","safeParse","success","Error","data","payload","metadata","wallet_relying_party","Array","isArray"],"sourceRoot":"../../../../src","sources":["credential/presentation/03-retrieve-jwks.ts"],"mappings":";;;;;;AAAA,IAAAA,IAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMG,gBAEZ,GAAG,eAAAA,CAAOC,SAAS,EAA4B;EAAA,IAA1B;IAAEC,OAAO,GAAG,CAAC;EAAE,CAAC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EACzC,MAAM;IAAEG,QAAQ,GAAGC;EAAM,CAAC,GAAGL,OAAO;EAEpC,MAAMM,YAAY,GAAG,IAAIC,GAAG,CAC1B,6BAA6B,EAC7BR,SACF,CAAC,CAACS,QAAQ,CAAC,CAAC;;EAEZ;EACA,MAAMC,IAAI,GAAG,MAAML,QAAQ,CAACE,YAAY,EAAE;IACxCI,MAAM,EAAE;EACV,CAAC,CAAC,CACCC,IAAI,CAAC,IAAAC,sBAAgB,EAAC,GAAG,CAAC,CAAC,CAC3BD,IAAI,CAAEE,GAAG,IAAKA,GAAG,CAACC,IAAI,CAAC,CAAC,CAAC,CACzBH,IAAI,CAAEG,IAAI,IAAKC,SAAI,CAACC,KAAK,CAACF,IAAI,CAAC,CAAC;EAEnC,OAAO;IACLG,IAAI,EAAER,IAAI,CAACQ;EACb,CAAC;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AANAC,OAAA,CAAApB,gBAAA,GAAAA,gBAAA;AAOO,MAAMqB,mBAEZ,GAAG,MAAOC,QAAQ,IAAK;EACtB,MAAMC,YAAY,GAAGC,sCAA+B,CAACC,SAAS,CAACH,QAAQ,CAAC;EACxE,IAAI,CAACC,YAAY,CAACG,OAAO,EAAE;IACzB,MAAM,IAAIC,KAAK,CAAC,sCAAsC,CAAC;EACzD;EAEA,MAAMhB,IAAI,GAAGY,YAAY,CAACK,IAAI,CAACC,OAAO,CAACC,QAAQ,CAACC,oBAAoB,CAACpB,IAAI;EAEzE,IAAI,CAACA,IAAI,IAAI,CAACqB,KAAK,CAACC,OAAO,CAACtB,IAAI,CAACQ,IAAI,CAAC,EAAE;IACtC,MAAM,IAAIQ,KAAK,CAAC,gDAAgD,CAAC;EACnE;EAEA,OAAO;IACLR,IAAI,EAAER,IAAI,CAACQ;EACb,CAAC;AACH,CAAC;AAACC,OAAA,CAAAC,mBAAA,GAAAA,mBAAA"}
@@ -1,82 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getRequestObject = void 0;
7
- var _reactNativeUuid = _interopRequireDefault(require("react-native-uuid"));
8
- var _ioReactNativeJwt = require("@pagopa/io-react-native-jwt");
9
- var _dpop = require("../../utils/dpop");
10
- var _errors = require("./errors");
11
- var _misc = require("../../utils/misc");
12
- var _types = require("./types");
13
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
- /**
15
- * Obtain the Request Object for RP authentication
16
- * @see https://italia.github.io/eudi-wallet-it-docs/versione-corrente/en/relying-party-solution.html
17
- *
18
- * @param requestUri The url for the Relying Party to connect with
19
- * @param rpConf The Relying Party's configuration
20
- * @param context.wiaCryptoContext The context to access the key associated with the Wallet Instance Attestation
21
- * @param context.walletInstanceAttestation The Wallet Instance Attestation token
22
- * @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
23
- * @returns The Request Object that describes the presentation
24
- */
25
- const getRequestObject = async (requestUri, _ref, jwkKeys) => {
26
- let {
27
- wiaCryptoContext,
28
- appFetch = fetch,
29
- walletInstanceAttestation
30
- } = _ref;
31
- const signedWalletInstanceDPoP = await (0, _dpop.createDPopToken)({
32
- jti: `${_reactNativeUuid.default.v4()}`,
33
- htm: "GET",
34
- htu: requestUri,
35
- ath: await (0, _ioReactNativeJwt.sha256ToBase64)(walletInstanceAttestation)
36
- }, wiaCryptoContext);
37
- const responseEncodedJwt = await appFetch(requestUri, {
38
- method: "GET",
39
- headers: {
40
- Authorization: `DPoP ${walletInstanceAttestation}`,
41
- DPoP: signedWalletInstanceDPoP
42
- }
43
- }).then((0, _misc.hasStatusOrThrow)(200)).then(res => res.json()).then(responseJson => responseJson.response);
44
- const responseJwt = (0, _ioReactNativeJwt.decode)(responseEncodedJwt);
45
- await verifyTokenSignature(jwkKeys, responseJwt);
46
-
47
- // Ensure that the request object conforms to the expected specification.
48
- const requestObject = _types.RequestObject.parse(responseJwt.payload);
49
- return {
50
- requestObject
51
- };
52
- };
53
- exports.getRequestObject = getRequestObject;
54
- const verifyTokenSignature = async (jwkKeys, responseJwt) => {
55
- var _responseJwt$protecte;
56
- // verify token signature to ensure the request object is authentic
57
- // 1. according to entity configuration if present
58
- if (jwkKeys) {
59
- const pubKey = jwkKeys.find(_ref2 => {
60
- let {
61
- kid
62
- } = _ref2;
63
- return kid === responseJwt.protectedHeader.kid;
64
- });
65
- if (!pubKey) {
66
- throw new _errors.NoSuitableKeysFoundInEntityConfiguration("Request Object signature verification");
67
- }
68
- await (0, _ioReactNativeJwt.verify)(responseJwt, pubKey);
69
- return;
70
- }
71
-
72
- // 2. If jwk is not retrieved from entity config, check if the token contains the 'jwk' attribute
73
- if ((_responseJwt$protecte = responseJwt.protectedHeader) !== null && _responseJwt$protecte !== void 0 && _responseJwt$protecte.jwk) {
74
- const pubKey = responseJwt.protectedHeader.jwk;
75
- await (0, _ioReactNativeJwt.verify)(responseJwt, pubKey);
76
- return;
77
- }
78
-
79
- // No verification condition matched: skipping signature verification for now.
80
- // TODO: [EUDIW-215] Remove skipping signature verification
81
- };
82
- //# sourceMappingURL=04-get-request-object.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_reactNativeUuid","_interopRequireDefault","require","_ioReactNativeJwt","_dpop","_errors","_misc","_types","obj","__esModule","default","getRequestObject","requestUri","_ref","jwkKeys","wiaCryptoContext","appFetch","fetch","walletInstanceAttestation","signedWalletInstanceDPoP","createDPopToken","jti","uuid","v4","htm","htu","ath","sha256ToBase64","responseEncodedJwt","method","headers","Authorization","DPoP","then","hasStatusOrThrow","res","json","responseJson","response","responseJwt","decodeJwt","verifyTokenSignature","requestObject","RequestObject","parse","payload","exports","_responseJwt$protecte","pubKey","find","_ref2","kid","protectedHeader","NoSuitableKeysFoundInEntityConfiguration","verify","jwk"],"sourceRoot":"../../../../src","sources":["credential/presentation/04-get-request-object.ts"],"mappings":";;;;;;AAAA,IAAAA,gBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,iBAAA,GAAAD,OAAA;AAOA,IAAAE,KAAA,GAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AAEA,IAAAI,KAAA,GAAAJ,OAAA;AAEA,IAAAK,MAAA,GAAAL,OAAA;AAAwC,SAAAD,uBAAAO,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAYxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMG,gBAAkC,GAAG,MAAAA,CAChDC,UAAU,EAAAC,IAAA,EAEVC,OAAO,KACJ;EAAA,IAFH;IAAEC,gBAAgB;IAAEC,QAAQ,GAAGC,KAAK;IAAEC;EAA0B,CAAC,GAAAL,IAAA;EAGjE,MAAMM,wBAAwB,GAAG,MAAM,IAAAC,qBAAe,EACpD;IACEC,GAAG,EAAG,GAAEC,wBAAI,CAACC,EAAE,CAAC,CAAE,EAAC;IACnBC,GAAG,EAAE,KAAK;IACVC,GAAG,EAAEb,UAAU;IACfc,GAAG,EAAE,MAAM,IAAAC,gCAAc,EAACT,yBAAyB;EACrD,CAAC,EACDH,gBACF,CAAC;EAED,MAAMa,kBAAkB,GAAG,MAAMZ,QAAQ,CAACJ,UAAU,EAAE;IACpDiB,MAAM,EAAE,KAAK;IACbC,OAAO,EAAE;MACPC,aAAa,EAAG,QAAOb,yBAA0B,EAAC;MAClDc,IAAI,EAAEb;IACR;EACF,CAAC,CAAC,CACCc,IAAI,CAAC,IAAAC,sBAAgB,EAAC,GAAG,CAAC,CAAC,CAC3BD,IAAI,CAAEE,GAAG,IAAKA,GAAG,CAACC,IAAI,CAAC,CAAC,CAAC,CACzBH,IAAI,CAAEI,YAAY,IAAKA,YAAY,CAACC,QAAQ,CAAC;EAEhD,MAAMC,WAAW,GAAG,IAAAC,wBAAS,EAACZ,kBAAkB,CAAC;EAEjD,MAAMa,oBAAoB,CAAC3B,OAAO,EAAEyB,WAAW,CAAC;;EAEhD;EACA,MAAMG,aAAa,GAAGC,oBAAa,CAACC,KAAK,CAACL,WAAW,CAACM,OAAO,CAAC;EAE9D,OAAO;IACLH;EACF,CAAC;AACH,CAAC;AAACI,OAAA,CAAAnC,gBAAA,GAAAA,gBAAA;AAEF,MAAM8B,oBAAoB,GAAG,MAAAA,CAC3B3B,OAAgC,EAChCyB,WAAiB,KACC;EAAA,IAAAQ,qBAAA;EAClB;EACA;EACA,IAAIjC,OAAO,EAAE;IACX,MAAMkC,MAAM,GAAGlC,OAAO,CAACmC,IAAI,CACzBC,KAAA;MAAA,IAAC;QAAEC;MAAI,CAAC,GAAAD,KAAA;MAAA,OAAKC,GAAG,KAAKZ,WAAW,CAACa,eAAe,CAACD,GAAG;IAAA,CACtD,CAAC;IACD,IAAI,CAACH,MAAM,EAAE;MACX,MAAM,IAAIK,gDAAwC,CAChD,uCACF,CAAC;IACH;IACA,MAAM,IAAAC,wBAAM,EAACf,WAAW,EAAES,MAAM,CAAC;IACjC;EACF;;EAEA;EACA,KAAAD,qBAAA,GAAIR,WAAW,CAACa,eAAe,cAAAL,qBAAA,eAA3BA,qBAAA,CAA6BQ,GAAG,EAAE;IACpC,MAAMP,MAAM,GAAGT,WAAW,CAACa,eAAe,CAACG,GAAG;IAC9C,MAAM,IAAAD,wBAAM,EAACf,WAAW,EAAES,MAAM,CAAC;IACjC;EACF;;EAEA;EACA;AACF,CAAC"}