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

Sign up to get free protection for your applications and to get access to all the features.
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
+ ]);