@pagopa/io-react-native-wallet 1.3.0 → 1.3.1

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 (50) hide show
  1. package/lib/commonjs/credential/issuance/06-obtain-credential.js +1 -1
  2. package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
  3. package/lib/commonjs/credential/issuance/types.js +1 -1
  4. package/lib/commonjs/credential/issuance/types.js.map +1 -1
  5. package/lib/commonjs/credential/presentation/03-get-request-object.js +2 -18
  6. package/lib/commonjs/credential/presentation/03-get-request-object.js.map +1 -1
  7. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +1 -1
  8. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
  9. package/lib/commonjs/credential/presentation/08-send-authorization-response.js +52 -12
  10. package/lib/commonjs/credential/presentation/08-send-authorization-response.js.map +1 -1
  11. package/lib/commonjs/credential/presentation/README.md +1 -3
  12. package/lib/commonjs/credential/presentation/index.js +6 -0
  13. package/lib/commonjs/credential/presentation/index.js.map +1 -1
  14. package/lib/commonjs/credential/presentation/types.js +19 -1
  15. package/lib/commonjs/credential/presentation/types.js.map +1 -1
  16. package/lib/module/credential/issuance/06-obtain-credential.js +1 -1
  17. package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
  18. package/lib/module/credential/issuance/types.js +1 -1
  19. package/lib/module/credential/issuance/types.js.map +1 -1
  20. package/lib/module/credential/presentation/03-get-request-object.js +2 -17
  21. package/lib/module/credential/presentation/03-get-request-object.js.map +1 -1
  22. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +1 -1
  23. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
  24. package/lib/module/credential/presentation/08-send-authorization-response.js +51 -11
  25. package/lib/module/credential/presentation/08-send-authorization-response.js.map +1 -1
  26. package/lib/module/credential/presentation/README.md +1 -3
  27. package/lib/module/credential/presentation/index.js +2 -2
  28. package/lib/module/credential/presentation/index.js.map +1 -1
  29. package/lib/module/credential/presentation/types.js +18 -0
  30. package/lib/module/credential/presentation/types.js.map +1 -1
  31. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -1
  32. package/lib/typescript/credential/issuance/types.d.ts +4 -4
  33. package/lib/typescript/credential/presentation/03-get-request-object.d.ts +0 -3
  34. package/lib/typescript/credential/presentation/03-get-request-object.d.ts.map +1 -1
  35. package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -1
  36. package/lib/typescript/credential/presentation/08-send-authorization-response.d.ts +23 -7
  37. package/lib/typescript/credential/presentation/08-send-authorization-response.d.ts.map +1 -1
  38. package/lib/typescript/credential/presentation/index.d.ts +3 -3
  39. package/lib/typescript/credential/presentation/index.d.ts.map +1 -1
  40. package/lib/typescript/credential/presentation/types.d.ts +26 -0
  41. package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/credential/issuance/06-obtain-credential.ts +6 -4
  44. package/src/credential/issuance/types.ts +1 -1
  45. package/src/credential/presentation/03-get-request-object.ts +1 -24
  46. package/src/credential/presentation/07-evaluate-input-descriptor.ts +2 -5
  47. package/src/credential/presentation/08-send-authorization-response.ts +70 -22
  48. package/src/credential/presentation/README.md +1 -3
  49. package/src/credential/presentation/index.ts +4 -0
  50. package/src/credential/presentation/types.ts +26 -0
@@ -9,7 +9,12 @@ import type { VerifyRequestObjectSignature } from "./05-verify-request-object";
9
9
  import { NoSuitableKeysFoundInEntityConfiguration } from "./errors";
10
10
  import { hasStatusOrThrow, type Out } from "../../utils/misc";
11
11
  import { disclose } from "../../sd-jwt";
12
- import { PresentationDefinition, type Presentation } from "./types";
12
+ import {
13
+ DirectAuthorizationBodyPayload,
14
+ ErrorResponse,
15
+ PresentationDefinition,
16
+ type Presentation,
17
+ } from "./types";
13
18
  import * as z from "zod";
14
19
  import type { JWK } from "../../utils/jwk";
15
20
 
@@ -125,19 +130,20 @@ export const prepareVpToken = async (
125
130
  * Builds a URL-encoded form body for a direct POST response without encryption.
126
131
  *
127
132
  * @param requestObject - Contains state, nonce, and other relevant info.
128
- * @param vpToken - The signed VP token to include.
129
- * @param presentationSubmission - Object mapping credential disclosures.
133
+ * @param payload - Object that contains either the VP token to encrypt and the stringified mapping of the credential disclosures or the error code
130
134
  * @returns A URL-encoded string suitable for an `application/x-www-form-urlencoded` POST body.
131
135
  */
132
136
  export const buildDirectPostBody = async (
133
137
  requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
134
- vpToken: string,
135
- presentationSubmission: Record<string, unknown>
138
+ payload: DirectAuthorizationBodyPayload
136
139
  ): Promise<string> => {
137
140
  const formUrlEncodedBody = new URLSearchParams({
138
141
  state: requestObject.state,
139
- presentation_submission: JSON.stringify(presentationSubmission),
140
- vp_token: vpToken,
142
+ ...Object.fromEntries(
143
+ Object.entries(payload).map(([key, value]) => {
144
+ return [key, typeof value === "object" ? JSON.stringify(value) : value];
145
+ })
146
+ ),
141
147
  });
142
148
 
143
149
  return formUrlEncodedBody.toString();
@@ -148,22 +154,19 @@ export const buildDirectPostBody = async (
148
154
  *
149
155
  * @param jwkKeys - Array of JWKs from the Relying Party for encryption.
150
156
  * @param requestObject - Contains state, nonce, and other relevant info.
151
- * @param vpToken - The signed VP token to encrypt.
152
- * @param presentationSubmission - Object mapping credential disclosures.
157
+ * @param payload - Object that contains either the VP token to encrypt and the mapping of the credential disclosures or the error code
153
158
  * @returns A URL-encoded string for an `application/x-www-form-urlencoded` POST body,
154
159
  * where `response` contains the encrypted JWE.
155
160
  */
156
161
  export const buildDirectPostJwtBody = async (
157
162
  jwkKeys: Out<FetchJwks>["keys"],
158
163
  requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
159
- vpToken: string,
160
- presentationSubmission: Record<string, unknown>
164
+ payload: DirectAuthorizationBodyPayload
161
165
  ): Promise<string> => {
162
166
  // Prepare the authorization response payload to be encrypted
163
167
  const authzResponsePayload = JSON.stringify({
164
168
  state: requestObject.state,
165
- presentation_submission: presentationSubmission,
166
- vp_token: vpToken,
169
+ ...payload,
167
170
  });
168
171
 
169
172
  // Choose a suitable RSA public key for encryption
@@ -233,17 +236,14 @@ export const sendAuthorizationResponse: SendAuthorizationResponse = async (
233
236
  // 2. Choose the appropriate request body builder based on response mode
234
237
  const requestBody =
235
238
  requestObject.response_mode === "direct_post.jwt"
236
- ? await buildDirectPostJwtBody(
237
- jwkKeys,
238
- requestObject,
239
+ ? await buildDirectPostJwtBody(jwkKeys, requestObject, {
239
240
  vp_token,
240
- presentation_submission
241
- )
242
- : await buildDirectPostBody(
243
- requestObject,
241
+ presentation_submission,
242
+ })
243
+ : await buildDirectPostBody(requestObject, {
244
244
  vp_token,
245
- presentation_submission
246
- );
245
+ presentation_submission: presentation_submission,
246
+ });
247
247
 
248
248
  // 3. Send the authorization response via HTTP POST and validate the response
249
249
  return await appFetch(requestObject.response_uri, {
@@ -257,3 +257,51 @@ export const sendAuthorizationResponse: SendAuthorizationResponse = async (
257
257
  .then((res) => res.json())
258
258
  .then(AuthorizationResponse.parse);
259
259
  };
260
+
261
+ /**
262
+ * Type definition for the function that sends the authorization response
263
+ * to the Relying Party, completing the presentation flow.
264
+ */
265
+ export type SendAuthorizationErrorResponse = (
266
+ requestObject: Out<VerifyRequestObjectSignature>["requestObject"],
267
+ error: ErrorResponse,
268
+ jwkKeys: Out<FetchJwks>["keys"],
269
+ context?: {
270
+ appFetch?: GlobalFetch["fetch"];
271
+ }
272
+ ) => Promise<AuthorizationResponse>;
273
+
274
+ /**
275
+ * Sends the authorization error response to the Relying Party (RP) using the specified `response_mode`.
276
+ * This function completes the presentation flow in an OpenID 4 Verifiable Presentations scenario.
277
+ *
278
+ * @param requestObject - The request details, including presentation requirements.
279
+ * @param error - The response error value
280
+ * @param jwkKeys - Array of JWKs from the Relying Party for optional encryption.
281
+ * @param context - Contains optional custom fetch implementation.
282
+ * @returns Parsed and validated authorization response from the Relying Party.
283
+ */
284
+ export const sendAuthorizationErrorResponse: SendAuthorizationErrorResponse =
285
+ async (
286
+ requestObject,
287
+ error,
288
+ jwkKeys,
289
+ { appFetch = fetch } = {}
290
+ ): Promise<AuthorizationResponse> => {
291
+ // 2. Choose the appropriate request body builder based on response mode
292
+ const requestBody =
293
+ requestObject.response_mode === "direct_post.jwt"
294
+ ? await buildDirectPostJwtBody(jwkKeys, requestObject, { error })
295
+ : await buildDirectPostBody(requestObject, { error });
296
+ // 3. Send the authorization error response via HTTP POST and validate the response
297
+ return await appFetch(requestObject.response_uri, {
298
+ method: "POST",
299
+ headers: {
300
+ "Content-Type": "application/x-www-form-urlencoded",
301
+ },
302
+ body: requestBody,
303
+ })
304
+ .then(hasStatusOrThrow(200))
305
+ .then((res) => res.json())
306
+ .then(AuthorizationResponse.parse);
307
+ };
@@ -62,9 +62,7 @@ const { rpConf } = await Credential.Presentation.evaluateRelyingPartyTrust(clien
62
62
 
63
63
  const { requestObjectEncodedJwt } =
64
64
  await Credential.Presentation.getRequestObject(requestURI, {
65
- wiaCryptoContext: wiaCryptoContext,
66
- appFetch: appFetch,
67
- walletInstanceAttestation: walletInstanceAttestation,
65
+ appFetch: appFetch
68
66
  });
69
67
 
70
68
  // Retrieve RP JWK
@@ -27,6 +27,8 @@ import {
27
27
  import {
28
28
  sendAuthorizationResponse,
29
29
  type SendAuthorizationResponse,
30
+ sendAuthorizationErrorResponse,
31
+ type SendAuthorizationErrorResponse,
30
32
  } from "./08-send-authorization-response";
31
33
  import * as Errors from "./errors";
32
34
 
@@ -40,6 +42,7 @@ export {
40
42
  fetchPresentDefinition,
41
43
  evaluateInputDescriptorForSdJwt4VC,
42
44
  sendAuthorizationResponse,
45
+ sendAuthorizationErrorResponse,
43
46
  Errors,
44
47
  };
45
48
  export type {
@@ -51,4 +54,5 @@ export type {
51
54
  FetchPresentationDefinition,
52
55
  EvaluateInputDescriptorSdJwt4VC,
53
56
  SendAuthorizationResponse,
57
+ SendAuthorizationErrorResponse,
54
58
  };
@@ -90,3 +90,29 @@ export const RequestObject = z.object({
90
90
  scope: z.string().optional(),
91
91
  presentation_definition: PresentationDefinition.optional(),
92
92
  });
93
+
94
+ /**
95
+ * This type models the possible error responses the OpenID4VP protocol allows for a presentation of a credential.
96
+ * See https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#name-error-response for more information.
97
+ */
98
+ export type ErrorResponse = z.infer<typeof ErrorResponse>;
99
+ export const ErrorResponse = z.enum([
100
+ "invalid_scope",
101
+ "invalid_request",
102
+ "invalid_client",
103
+ "access_denied",
104
+ ]);
105
+
106
+ /**
107
+ * Type that defines the possible payload formats accepted by {@link buildDirectPostJwtBody} and {@link buildDirectPostBody}
108
+ */
109
+ export type DirectAuthorizationBodyPayload = z.infer<
110
+ typeof DirectAuthorizationBodyPayload
111
+ >;
112
+ export const DirectAuthorizationBodyPayload = z.union([
113
+ z.object({
114
+ vp_token: z.string(),
115
+ presentation_submission: z.record(z.string(), z.unknown()),
116
+ }),
117
+ z.object({ error: ErrorResponse }),
118
+ ]);