@pagopa/io-react-native-wallet 3.3.0 → 3.4.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 (170) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/credential/issuance/README.md +32 -14
  3. package/lib/commonjs/credential/issuance/api/IssuerConfig.js +1 -0
  4. package/lib/commonjs/credential/issuance/api/IssuerConfig.js.map +1 -1
  5. package/lib/commonjs/credential/issuance/common/06-verify-and-parse-credential.mdoc.js +6 -12
  6. package/lib/commonjs/credential/issuance/common/06-verify-and-parse-credential.mdoc.js.map +1 -1
  7. package/lib/commonjs/credential/issuance/common/06-verify-and-parse-credential.sdjwt.js +5 -3
  8. package/lib/commonjs/credential/issuance/common/06-verify-and-parse-credential.sdjwt.js.map +1 -1
  9. package/lib/commonjs/credential/issuance/v1.0.0/02-start-user-authorization.js +2 -1
  10. package/lib/commonjs/credential/issuance/v1.0.0/02-start-user-authorization.js.map +1 -1
  11. package/lib/commonjs/credential/issuance/v1.0.0/03-complete-user-authorization.js +8 -5
  12. package/lib/commonjs/credential/issuance/v1.0.0/03-complete-user-authorization.js.map +1 -1
  13. package/lib/commonjs/credential/issuance/v1.0.0/index.js +2 -1
  14. package/lib/commonjs/credential/issuance/v1.0.0/index.js.map +1 -1
  15. package/lib/commonjs/credential/issuance/v1.0.0/mappers.js +3 -1
  16. package/lib/commonjs/credential/issuance/v1.0.0/mappers.js.map +1 -1
  17. package/lib/commonjs/credential/issuance/v1.3.3/02-start-user-authorization.js +1 -1
  18. package/lib/commonjs/credential/issuance/v1.3.3/02-start-user-authorization.js.map +1 -1
  19. package/lib/commonjs/credential/issuance/v1.3.3/03-complete-user-authorization.js +108 -69
  20. package/lib/commonjs/credential/issuance/v1.3.3/03-complete-user-authorization.js.map +1 -1
  21. package/lib/commonjs/credential/issuance/v1.3.3/05-obtain-credential.js +4 -1
  22. package/lib/commonjs/credential/issuance/v1.3.3/05-obtain-credential.js.map +1 -1
  23. package/lib/commonjs/credential/issuance/v1.3.3/index.js +2 -1
  24. package/lib/commonjs/credential/issuance/v1.3.3/index.js.map +1 -1
  25. package/lib/commonjs/credential/issuance/v1.3.3/mappers.js +9 -10
  26. package/lib/commonjs/credential/issuance/v1.3.3/mappers.js.map +1 -1
  27. package/lib/commonjs/credential/presentation/api/types.js.map +1 -1
  28. package/lib/commonjs/credential/presentation/common/utils/http.js +9 -4
  29. package/lib/commonjs/credential/presentation/common/utils/http.js.map +1 -1
  30. package/lib/commonjs/credential/presentation/v1.0.0/07-send-authorization-response.js +3 -1
  31. package/lib/commonjs/credential/presentation/v1.0.0/07-send-authorization-response.js.map +1 -1
  32. package/lib/commonjs/credential/presentation/v1.3.3/05-verify-request-object.js +11 -10
  33. package/lib/commonjs/credential/presentation/v1.3.3/05-verify-request-object.js.map +1 -1
  34. package/lib/commonjs/credential/presentation/v1.3.3/07-send-authorization-response.js +2 -0
  35. package/lib/commonjs/credential/presentation/v1.3.3/07-send-authorization-response.js.map +1 -1
  36. package/lib/commonjs/credential/presentation/v1.3.3/mappers.js +1 -1
  37. package/lib/commonjs/credential/presentation/v1.3.3/mappers.js.map +1 -1
  38. package/lib/commonjs/credentials-catalogue/api/DigitalCredentialsCatalogue.js +2 -1
  39. package/lib/commonjs/credentials-catalogue/api/DigitalCredentialsCatalogue.js.map +1 -1
  40. package/lib/commonjs/credentials-catalogue/common/get-status-l10n-ids.js +23 -0
  41. package/lib/commonjs/credentials-catalogue/common/get-status-l10n-ids.js.map +1 -0
  42. package/lib/commonjs/credentials-catalogue/v1.0.0/index.js +3 -1
  43. package/lib/commonjs/credentials-catalogue/v1.0.0/index.js.map +1 -1
  44. package/lib/commonjs/credentials-catalogue/v1.3.3/index.js +3 -1
  45. package/lib/commonjs/credentials-catalogue/v1.3.3/index.js.map +1 -1
  46. package/lib/commonjs/utils/config.js +9 -1
  47. package/lib/commonjs/utils/config.js.map +1 -1
  48. package/lib/module/credential/issuance/README.md +32 -14
  49. package/lib/module/credential/issuance/api/IssuerConfig.js +1 -0
  50. package/lib/module/credential/issuance/api/IssuerConfig.js.map +1 -1
  51. package/lib/module/credential/issuance/common/06-verify-and-parse-credential.mdoc.js +6 -12
  52. package/lib/module/credential/issuance/common/06-verify-and-parse-credential.mdoc.js.map +1 -1
  53. package/lib/module/credential/issuance/common/06-verify-and-parse-credential.sdjwt.js +5 -3
  54. package/lib/module/credential/issuance/common/06-verify-and-parse-credential.sdjwt.js.map +1 -1
  55. package/lib/module/credential/issuance/v1.0.0/02-start-user-authorization.js +2 -1
  56. package/lib/module/credential/issuance/v1.0.0/02-start-user-authorization.js.map +1 -1
  57. package/lib/module/credential/issuance/v1.0.0/03-complete-user-authorization.js +6 -4
  58. package/lib/module/credential/issuance/v1.0.0/03-complete-user-authorization.js.map +1 -1
  59. package/lib/module/credential/issuance/v1.0.0/index.js +3 -2
  60. package/lib/module/credential/issuance/v1.0.0/index.js.map +1 -1
  61. package/lib/module/credential/issuance/v1.0.0/mappers.js +3 -1
  62. package/lib/module/credential/issuance/v1.0.0/mappers.js.map +1 -1
  63. package/lib/module/credential/issuance/v1.3.3/02-start-user-authorization.js +1 -1
  64. package/lib/module/credential/issuance/v1.3.3/02-start-user-authorization.js.map +1 -1
  65. package/lib/module/credential/issuance/v1.3.3/03-complete-user-authorization.js +108 -70
  66. package/lib/module/credential/issuance/v1.3.3/03-complete-user-authorization.js.map +1 -1
  67. package/lib/module/credential/issuance/v1.3.3/05-obtain-credential.js +4 -1
  68. package/lib/module/credential/issuance/v1.3.3/05-obtain-credential.js.map +1 -1
  69. package/lib/module/credential/issuance/v1.3.3/index.js +3 -2
  70. package/lib/module/credential/issuance/v1.3.3/index.js.map +1 -1
  71. package/lib/module/credential/issuance/v1.3.3/mappers.js +9 -10
  72. package/lib/module/credential/issuance/v1.3.3/mappers.js.map +1 -1
  73. package/lib/module/credential/presentation/api/types.js.map +1 -1
  74. package/lib/module/credential/presentation/common/utils/http.js +9 -4
  75. package/lib/module/credential/presentation/common/utils/http.js.map +1 -1
  76. package/lib/module/credential/presentation/v1.0.0/07-send-authorization-response.js +3 -1
  77. package/lib/module/credential/presentation/v1.0.0/07-send-authorization-response.js.map +1 -1
  78. package/lib/module/credential/presentation/v1.3.3/05-verify-request-object.js +11 -10
  79. package/lib/module/credential/presentation/v1.3.3/05-verify-request-object.js.map +1 -1
  80. package/lib/module/credential/presentation/v1.3.3/07-send-authorization-response.js +2 -0
  81. package/lib/module/credential/presentation/v1.3.3/07-send-authorization-response.js.map +1 -1
  82. package/lib/module/credential/presentation/v1.3.3/mappers.js +1 -1
  83. package/lib/module/credential/presentation/v1.3.3/mappers.js.map +1 -1
  84. package/lib/module/credentials-catalogue/api/DigitalCredentialsCatalogue.js +1 -1
  85. package/lib/module/credentials-catalogue/api/DigitalCredentialsCatalogue.js.map +1 -1
  86. package/lib/module/credentials-catalogue/common/get-status-l10n-ids.js +16 -0
  87. package/lib/module/credentials-catalogue/common/get-status-l10n-ids.js.map +1 -0
  88. package/lib/module/credentials-catalogue/v1.0.0/index.js +3 -1
  89. package/lib/module/credentials-catalogue/v1.0.0/index.js.map +1 -1
  90. package/lib/module/credentials-catalogue/v1.3.3/index.js +3 -1
  91. package/lib/module/credentials-catalogue/v1.3.3/index.js.map +1 -1
  92. package/lib/module/utils/config.js +7 -0
  93. package/lib/module/utils/config.js.map +1 -1
  94. package/lib/typescript/credential/issuance/api/02-start-user-authorization.d.ts +1 -0
  95. package/lib/typescript/credential/issuance/api/02-start-user-authorization.d.ts.map +1 -1
  96. package/lib/typescript/credential/issuance/api/03-complete-user-authorization.d.ts +19 -5
  97. package/lib/typescript/credential/issuance/api/03-complete-user-authorization.d.ts.map +1 -1
  98. package/lib/typescript/credential/issuance/api/IssuerConfig.d.ts +1 -0
  99. package/lib/typescript/credential/issuance/api/IssuerConfig.d.ts.map +1 -1
  100. package/lib/typescript/credential/issuance/common/06-verify-and-parse-credential.mdoc.d.ts.map +1 -1
  101. package/lib/typescript/credential/issuance/common/06-verify-and-parse-credential.sdjwt.d.ts.map +1 -1
  102. package/lib/typescript/credential/issuance/v1.0.0/02-start-user-authorization.d.ts.map +1 -1
  103. package/lib/typescript/credential/issuance/v1.0.0/03-complete-user-authorization.d.ts +2 -1
  104. package/lib/typescript/credential/issuance/v1.0.0/03-complete-user-authorization.d.ts.map +1 -1
  105. package/lib/typescript/credential/issuance/v1.0.0/index.d.ts.map +1 -1
  106. package/lib/typescript/credential/issuance/v1.0.0/mappers.d.ts +1 -0
  107. package/lib/typescript/credential/issuance/v1.0.0/mappers.d.ts.map +1 -1
  108. package/lib/typescript/credential/issuance/v1.3.3/03-complete-user-authorization.d.ts +2 -1
  109. package/lib/typescript/credential/issuance/v1.3.3/03-complete-user-authorization.d.ts.map +1 -1
  110. package/lib/typescript/credential/issuance/v1.3.3/05-obtain-credential.d.ts.map +1 -1
  111. package/lib/typescript/credential/issuance/v1.3.3/index.d.ts.map +1 -1
  112. package/lib/typescript/credential/issuance/v1.3.3/mappers.d.ts +7 -4
  113. package/lib/typescript/credential/issuance/v1.3.3/mappers.d.ts.map +1 -1
  114. package/lib/typescript/credential/presentation/api/05-verify-request-object.d.ts +1 -1
  115. package/lib/typescript/credential/presentation/api/types.d.ts +3 -7
  116. package/lib/typescript/credential/presentation/api/types.d.ts.map +1 -1
  117. package/lib/typescript/credential/presentation/common/utils/http.d.ts +1 -1
  118. package/lib/typescript/credential/presentation/common/utils/http.d.ts.map +1 -1
  119. package/lib/typescript/credential/presentation/v1.3.3/05-verify-request-object.d.ts.map +1 -1
  120. package/lib/typescript/credential/presentation/v1.3.3/07-send-authorization-response.d.ts.map +1 -1
  121. package/lib/typescript/credential/presentation/v1.3.3/mappers.d.ts +8 -8
  122. package/lib/typescript/credential/presentation/v1.3.3/types.d.ts +8 -8
  123. package/lib/typescript/credentials-catalogue/api/DigitalCredentialsCatalogue.d.ts +6 -0
  124. package/lib/typescript/credentials-catalogue/api/DigitalCredentialsCatalogue.d.ts.map +1 -1
  125. package/lib/typescript/credentials-catalogue/api/index.d.ts +14 -2
  126. package/lib/typescript/credentials-catalogue/api/index.d.ts.map +1 -1
  127. package/lib/typescript/credentials-catalogue/common/get-status-l10n-ids.d.ts +9 -0
  128. package/lib/typescript/credentials-catalogue/common/get-status-l10n-ids.d.ts.map +1 -0
  129. package/lib/typescript/credentials-catalogue/v1.0.0/index.d.ts.map +1 -1
  130. package/lib/typescript/credentials-catalogue/v1.3.3/index.d.ts.map +1 -1
  131. package/lib/typescript/trust/v1.3.3/types.d.ts +6 -4
  132. package/lib/typescript/trust/v1.3.3/types.d.ts.map +1 -1
  133. package/lib/typescript/utils/config.d.ts +4 -0
  134. package/lib/typescript/utils/config.d.ts.map +1 -1
  135. package/package.json +6 -6
  136. package/src/credential/issuance/README.md +32 -14
  137. package/src/credential/issuance/api/02-start-user-authorization.ts +1 -0
  138. package/src/credential/issuance/api/03-complete-user-authorization.ts +26 -5
  139. package/src/credential/issuance/api/IssuerConfig.ts +1 -0
  140. package/src/credential/issuance/common/06-verify-and-parse-credential.mdoc.ts +4 -20
  141. package/src/credential/issuance/common/06-verify-and-parse-credential.sdjwt.ts +8 -4
  142. package/src/credential/issuance/v1.0.0/02-start-user-authorization.ts +7 -1
  143. package/src/credential/issuance/v1.0.0/03-complete-user-authorization.ts +16 -4
  144. package/src/credential/issuance/v1.0.0/index.ts +4 -2
  145. package/src/credential/issuance/v1.0.0/mappers.ts +5 -0
  146. package/src/credential/issuance/v1.3.3/02-start-user-authorization.ts +1 -1
  147. package/src/credential/issuance/v1.3.3/03-complete-user-authorization.ts +141 -94
  148. package/src/credential/issuance/v1.3.3/05-obtain-credential.ts +7 -1
  149. package/src/credential/issuance/v1.3.3/index.ts +4 -2
  150. package/src/credential/issuance/v1.3.3/mappers.ts +9 -10
  151. package/src/credential/presentation/api/05-verify-request-object.ts +1 -1
  152. package/src/credential/presentation/api/types.ts +3 -7
  153. package/src/credential/presentation/common/utils/http.ts +2 -2
  154. package/src/credential/presentation/v1.0.0/07-send-authorization-response.ts +1 -1
  155. package/src/credential/presentation/v1.3.3/05-verify-request-object.ts +15 -14
  156. package/src/credential/presentation/v1.3.3/07-send-authorization-response.ts +2 -0
  157. package/src/credential/presentation/v1.3.3/mappers.ts +1 -1
  158. package/src/credentials-catalogue/api/DigitalCredentialsCatalogue.ts +4 -1
  159. package/src/credentials-catalogue/api/index.ts +15 -0
  160. package/src/credentials-catalogue/common/get-status-l10n-ids.ts +25 -0
  161. package/src/credentials-catalogue/v1.0.0/index.ts +2 -0
  162. package/src/credentials-catalogue/v1.3.3/index.ts +2 -0
  163. package/src/utils/config.ts +7 -0
  164. package/lib/commonjs/credential/presentation/common/utils.js +0 -28
  165. package/lib/commonjs/credential/presentation/common/utils.js.map +0 -1
  166. package/lib/module/credential/presentation/common/utils.js +0 -21
  167. package/lib/module/credential/presentation/common/utils.js.map +0 -1
  168. package/lib/typescript/credential/presentation/common/utils.d.ts +0 -11
  169. package/lib/typescript/credential/presentation/common/utils.d.ts.map +0 -1
  170. package/src/credential/presentation/common/utils.ts +0 -30
@@ -39,10 +39,32 @@ export interface CompleteUserAuthorizationApi {
39
39
  * @param authRedirectUrl The URL to which the end user should be redirected to start the authentication flow
40
40
  * @returns the authorization response which contains code, state and iss
41
41
  */
42
- completeUserAuthorizationWithQueryMode(
42
+ completePidUserAuthorizationWithQueryMode(
43
43
  authRedirectUrl: string
44
44
  ): Promise<AuthorizationResult>;
45
45
 
46
+ /**
47
+ * Complete user authorization when the response mode is "query" and the requested credential is an Electronic Attestation of Attributes (EAA).
48
+ * This type of credentials requires a PID to be presented to complete the authorization process and then obtain an access token.
49
+ * @since 1.3.3
50
+ *
51
+ * @param requestObject The request object containing the necessary parameters for authorization.
52
+ * @param issuerConfig The issuer configuration returned by {@link evaluateIssuerTrust}
53
+ * @param pid The PID to present as a tuple [keyTag, credential].
54
+ * @param redirectUri The client redirect URI to which the authorization server will redirect after completing the authorization process.
55
+ * @param appFetch (optional) fetch api implementation. Default: built-in fetch
56
+ * @returns The authorization response which contains code, state and iss
57
+ */
58
+ completeEaaUserAuthorizationWithQueryMode(
59
+ requestObject: RequestObject,
60
+ issuerConf: IssuerConfig,
61
+ pid: [keyTag: string, credential: string],
62
+ redirectUri: string,
63
+ context?: {
64
+ appFetch?: GlobalFetch["fetch"];
65
+ }
66
+ ): Promise<AuthorizationResult>;
67
+
46
68
  /**
47
69
  * WARNING: This function must be called after {@link getRequestedCredentialToBePresented}. The next function to be called is {@link authorizeAccess}.
48
70
  *
@@ -51,8 +73,8 @@ export interface CompleteUserAuthorizationApi {
51
73
  * Following this,the redirect_uri from the response is used to obtain the final authorization response.
52
74
  * @since 1.0.0
53
75
  *
54
- * @param requestObject - The request object containing the necessary parameters for authorization.
55
- * @param pid The `PID` that must be presented for the issuance of credentials.
76
+ * @param requestObject The request object containing the necessary parameters for authorization.
77
+ * @param pid The PID to present as a tuple [keyTag, credential].
56
78
  * @param appFetch (optional) fetch api implementation. Default: built-in fetch
57
79
  * @returns the authorization response which contains code, state and iss
58
80
  * @throws {ValidationFailed} if an error while validating the response
@@ -60,10 +82,9 @@ export interface CompleteUserAuthorizationApi {
60
82
  completeUserAuthorizationWithFormPostJwtMode(
61
83
  requestObject: RequestObject,
62
84
  issuerConf: IssuerConfig,
63
- pid: string,
85
+ pid: [keyTag: string, credential: string],
64
86
  context: {
65
87
  wiaCryptoContext: CryptoContext;
66
- pidKeyTag: string;
67
88
  appFetch?: GlobalFetch["fetch"];
68
89
  }
69
90
  ): Promise<AuthorizationResult>;
@@ -60,6 +60,7 @@ export const IssuerConfig = z.object({
60
60
  credential_configurations_supported: z.record(z.string(), CredentialConfig),
61
61
  federation_entity: FederationEntityMetadata,
62
62
  credential_issuance_batch_size: z.number().optional(),
63
+ encrypted_response_enc_values_supported: z.array(z.string()).optional(),
63
64
  /**
64
65
  * @deprecated
65
66
  */
@@ -1,12 +1,10 @@
1
1
  import type { CBOR } from "@pagopa/io-react-native-iso18013";
2
2
  import type { CryptoContext } from "@pagopa/io-react-native-jwt";
3
3
  import type { PublicKey } from "@pagopa/io-react-native-crypto";
4
- import { extractElementValueAsDate } from "../../../mdoc/converter";
5
4
  import {
6
5
  getParsedCredentialClaimKey,
7
6
  verify as verifyMdoc,
8
7
  } from "../../../mdoc";
9
- import { MDOC_DEFAULT_NAMESPACE } from "../../../mdoc/const";
10
8
  import { IoWalletError } from "../../../utils/errors";
11
9
  import type { Out } from "../../../utils/misc";
12
10
  import { isSameThumbprint } from "../../../utils/jwk";
@@ -209,28 +207,14 @@ export const verifyAndParseCredentialMDoc: IssuanceApi["verifyAndParseCredential
209
207
  ignoreMissingAttributes
210
208
  );
211
209
 
212
- const expirationDate = extractElementValueAsDate(
213
- parsedCredential?.[
214
- getParsedCredentialClaimKey(MDOC_DEFAULT_NAMESPACE, "expiry_date")
215
- ]?.value as string
216
- );
217
- if (!expirationDate) {
218
- throw new IoWalletError(`expirationDate must be present!!`);
219
- }
220
- expirationDate.setDate(expirationDate.getDate() + 1);
221
-
222
- const maybeIssuedAt = extractElementValueAsDate(
223
- parsedCredential?.[
224
- getParsedCredentialClaimKey(MDOC_DEFAULT_NAMESPACE, "issue_date")
225
- ]?.value as string
226
- );
227
- maybeIssuedAt?.setDate(maybeIssuedAt.getDate() + 1);
210
+ const { signed, validUntil } =
211
+ decoded.issuerSigned.issuerAuth.payload.validityInfo;
228
212
 
229
213
  return {
230
214
  parsedCredential,
231
215
  credential,
232
216
  credentialConfigurationId,
233
- expiration: expirationDate,
234
- issuedAt: maybeIssuedAt ?? undefined,
217
+ expiration: validUntil,
218
+ issuedAt: signed,
235
219
  };
236
220
  };
@@ -2,7 +2,7 @@ import {
2
2
  type CryptoContext,
3
3
  verify as verifyJwt,
4
4
  } from "@pagopa/io-react-native-jwt";
5
- import { type SDJwt, SDJwtInstance } from "@sd-jwt/core";
5
+ import { type SDJwt, type VerifierOptions, SDJwtInstance } from "@sd-jwt/core";
6
6
  import { digest } from "@sd-jwt/crypto-nodejs";
7
7
  import type { Verifier } from "@sd-jwt/types";
8
8
  import { isPathEqual, isPrefixOf } from "../../../utils/parser";
@@ -153,12 +153,14 @@ const parseCredentialSdJwt = (
153
153
  return processLevel(parsedCredentialRaw, []) as ParsedCredential;
154
154
  };
155
155
 
156
+ type SdJwtInstanceVerifier = Verifier<VerifierOptions & { issuerKeys: JWK[] }>;
157
+
156
158
  /**
157
159
  * JWT verifier implementing the interface expected by the SD-JWT library.
158
160
  * Verification is delegated to `io-react-native-jwt` to leverage its support for multiple algorithms.
159
161
  * @returns Boolean indicating whether the verification succeeded or not
160
162
  */
161
- const sdJwtInstanceVerifier: Verifier<{ issuerKeys: JWK[] }> = async (
163
+ const sdJwtInstanceVerifier: SdJwtInstanceVerifier = async (
162
164
  data,
163
165
  signature,
164
166
  options
@@ -167,7 +169,9 @@ const sdJwtInstanceVerifier: Verifier<{ issuerKeys: JWK[] }> = async (
167
169
  return false;
168
170
  }
169
171
  try {
170
- await verifyJwt(`${data}.${signature}`, options.issuerKeys);
172
+ await verifyJwt(`${data}.${signature}`, options.issuerKeys, {
173
+ clockTolerance: options.skewSeconds,
174
+ });
171
175
  return true;
172
176
  } catch {
173
177
  return false;
@@ -200,7 +204,7 @@ async function verifyCredentialSdJwt(
200
204
  });
201
205
 
202
206
  const [verifiedCredential, holderBindingKey] = await Promise.all([
203
- sdJwtInstance.verify(rawCredential, { issuerKeys }),
207
+ sdJwtInstance.verify(rawCredential, { issuerKeys, skewSeconds: 30 }),
204
208
  holderBindingContext.getPublicKey(),
205
209
  ]);
206
210
 
@@ -64,5 +64,11 @@ export const startUserAuthorization: IssuanceApi["startUserAuthorization"] =
64
64
  }
65
65
  );
66
66
 
67
- return { issuerRequestUri, clientId, codeVerifier, credentialDefinition };
67
+ return {
68
+ issuerRequestUri,
69
+ clientId,
70
+ codeVerifier,
71
+ credentialDefinition,
72
+ responseMode,
73
+ };
68
74
  };
@@ -7,7 +7,11 @@ import {
7
7
  import { hasStatusOrThrow } from "../../../utils/misc";
8
8
  import parseUrl from "parse-url";
9
9
  import type { DcqlQuery } from "dcql";
10
- import { IssuerResponseError, ValidationFailed } from "../../../utils/errors";
10
+ import {
11
+ IssuerResponseError,
12
+ UnimplementedFeatureError,
13
+ ValidationFailed,
14
+ } from "../../../utils/errors";
11
15
  import {
12
16
  decode,
13
17
  SignJWT,
@@ -70,7 +74,7 @@ export const buildAuthorizationUrl: IssuanceApi["buildAuthorizationUrl"] =
70
74
  return { authUrl };
71
75
  };
72
76
 
73
- export const completeUserAuthorizationWithQueryMode: IssuanceApi["completeUserAuthorizationWithQueryMode"] =
77
+ export const completePidUserAuthorizationWithQueryMode: IssuanceApi["completePidUserAuthorizationWithQueryMode"] =
74
78
  async (authRedirectUrl) => {
75
79
  Logger.log(
76
80
  LogLevel.DEBUG,
@@ -81,6 +85,14 @@ export const completeUserAuthorizationWithQueryMode: IssuanceApi["completeUserAu
81
85
  return parseAuthorizationResponse(query);
82
86
  };
83
87
 
88
+ export const completeEaaUserAuthorizationWithQueryMode: IssuanceApi["completeEaaUserAuthorizationWithQueryMode"] =
89
+ () => {
90
+ throw new UnimplementedFeatureError(
91
+ "completeEaaUserAuthorizationWithQueryMode",
92
+ "1.0.0"
93
+ );
94
+ };
95
+
84
96
  export const getRequestedCredentialToBePresented: IssuanceApi["getRequestedCredentialToBePresented"] =
85
97
  async (issuerRequestUri, clientId, issuerConf, appFetch = fetch) => {
86
98
  Logger.log(
@@ -130,7 +142,7 @@ export const completeUserAuthorizationWithFormPostJwtMode: IssuanceApi["complete
130
142
  requestObject,
131
143
  _issuerConfig,
132
144
  pid,
133
- { wiaCryptoContext, pidKeyTag, appFetch = fetch }
145
+ { wiaCryptoContext, appFetch = fetch }
134
146
  ) => {
135
147
  Logger.log(
136
148
  LogLevel.DEBUG,
@@ -139,7 +151,7 @@ export const completeUserAuthorizationWithFormPostJwtMode: IssuanceApi["complete
139
151
 
140
152
  const dcqlQueryResult = await RemotePresentationFlow.evaluateDcqlQuery(
141
153
  requestObject.dcql_query as DcqlQuery,
142
- [[pidKeyTag, pid]]
154
+ [pid]
143
155
  );
144
156
 
145
157
  const authRequestObject = {
@@ -3,7 +3,8 @@ import { evaluateIssuerTrust } from "./01-evaluate-issuer-trust";
3
3
  import { startUserAuthorization } from "./02-start-user-authorization";
4
4
  import {
5
5
  continueUserAuthorizationWithMRTDPoPChallenge,
6
- completeUserAuthorizationWithQueryMode,
6
+ completePidUserAuthorizationWithQueryMode,
7
+ completeEaaUserAuthorizationWithQueryMode,
7
8
  completeUserAuthorizationWithFormPostJwtMode,
8
9
  buildAuthorizationUrl,
9
10
  getRequestedCredentialToBePresented,
@@ -20,7 +21,8 @@ export const Issuance: IssuanceApi = {
20
21
  evaluateIssuerTrust,
21
22
  startUserAuthorization,
22
23
  buildAuthorizationUrl,
23
- completeUserAuthorizationWithQueryMode,
24
+ completePidUserAuthorizationWithQueryMode,
25
+ completeEaaUserAuthorizationWithQueryMode,
24
26
  continueUserAuthorizationWithMRTDPoPChallenge,
25
27
  getRequestedCredentialToBePresented,
26
28
  completeUserAuthorizationWithFormPostJwtMode,
@@ -9,6 +9,7 @@ export const mapToIssuerConfig = createMapper<
9
9
  const {
10
10
  oauth_authorization_server,
11
11
  openid_credential_issuer,
12
+ openid_credential_verifier,
12
13
  federation_entity,
13
14
  } = x.payload.metadata;
14
15
  return {
@@ -28,5 +29,9 @@ export const mapToIssuerConfig = createMapper<
28
29
  openid_credential_issuer.status_attestation_endpoint,
29
30
  nonce_endpoint: openid_credential_issuer.nonce_endpoint,
30
31
  federation_entity,
32
+ encrypted_response_enc_values_supported:
33
+ openid_credential_verifier?.authorization_encrypted_response_enc
34
+ ? [openid_credential_verifier.authorization_encrypted_response_enc]
35
+ : undefined,
31
36
  };
32
37
  });
@@ -88,7 +88,7 @@ export const startUserAuthorization: IssuanceApi["startUserAuthorization"] =
88
88
  signJwt,
89
89
  },
90
90
  clientAttestation: walletInstanceAttestation,
91
- authorizationServer: issuerConf.authorization_endpoint,
91
+ authorizationServer: issuerConf.credential_issuer,
92
92
  signer: wiaSigner,
93
93
  jti: uuidv4(),
94
94
  });
@@ -6,30 +6,33 @@ import {
6
6
  import parseUrl from "parse-url";
7
7
  import type { DcqlQuery } from "dcql";
8
8
  import {
9
- fetchAuthorizationRequest,
9
+ createAuthorizationResponse,
10
10
  parseAuthorizeRequest,
11
+ fetchAuthorizationResponse,
12
+ type CreateAuthorizationResponseResult,
11
13
  } from "@pagopa/io-wallet-oid4vp";
12
14
  import { sendAuthorizationResponseAndExtractCode } from "@pagopa/io-wallet-oid4vci";
15
+ import type { jsonWebKeySet } from "@pagopa/io-wallet-oid-federation";
13
16
  import { parseMrtdChallenge } from "@pagopa/io-wallet-oauth2";
14
- import { SignJWT, type CryptoContext } from "@pagopa/io-react-native-jwt";
15
17
  import { AuthorizationError, AuthorizationIdpError } from "../common/errors";
16
18
  import { LogLevel, Logger } from "../../../utils/logging";
17
19
  import { RemotePresentation as RemotePresentationFlow } from "../../presentation/v1.3.3";
18
- import { partialCallbacks } from "../../../utils/callbacks";
19
- import { sdkConfigV1_3 } from "../../../utils/config";
20
20
  import {
21
- IoWalletError,
22
- sdkUnexpectedStatusCodeToIssuerError,
23
- } from "../../../utils/errors";
24
- import type { IssuanceApi } from "../api";
21
+ createVerifyJwtFromJwks,
22
+ partialCallbacks,
23
+ } from "../../../utils/callbacks";
24
+ import { sdkConfigV1_3, sdkConfigV1_4 } from "../../../utils/config";
25
+ import { IoWalletError, IssuerResponseError } from "../../../utils/errors";
26
+ import type { IssuanceApi, IssuerConfig } from "../api";
25
27
  import { mapToRequestObject } from "./mappers";
26
- import type { RemotePresentation } from "../../presentation";
28
+ import type { RequestObject } from "../../presentation";
29
+ import { hasStatusOrThrow } from "../../../utils/misc";
27
30
 
28
31
  export const continueUserAuthorizationWithMRTDPoPChallenge: IssuanceApi["continueUserAuthorizationWithMRTDPoPChallenge"] =
29
32
  async (authRedirectUrl) => {
30
33
  Logger.log(
31
34
  LogLevel.DEBUG,
32
- `The requested credential is a PersonIdentificationData and requires MRTD PoP, starting MRTD PoP validation from auth redirect`
35
+ "The requested credential is a PID and requires MRTD PoP, starting MRTD PoP validation from auth redirect"
33
36
  );
34
37
  try {
35
38
  const parsedChallenge = parseMrtdChallenge({
@@ -65,11 +68,11 @@ export const buildAuthorizationUrl: IssuanceApi["buildAuthorizationUrl"] =
65
68
  return { authUrl };
66
69
  };
67
70
 
68
- export const completeUserAuthorizationWithQueryMode: IssuanceApi["completeUserAuthorizationWithQueryMode"] =
71
+ export const completePidUserAuthorizationWithQueryMode: IssuanceApi["completePidUserAuthorizationWithQueryMode"] =
69
72
  async (authRedirectUrl) => {
70
73
  Logger.log(
71
74
  LogLevel.DEBUG,
72
- `The requested credential is a PersonIdentificationData, completing the user authorization with query mode`
75
+ "The requested credential is a PID, completing the user authorization with query mode"
73
76
  );
74
77
  const query = parseUrl(authRedirectUrl).query;
75
78
 
@@ -80,7 +83,7 @@ export const getRequestedCredentialToBePresented: IssuanceApi["getRequestedCrede
80
83
  async (issuerRequestUri, clientId, issuerConf, appFetch = fetch) => {
81
84
  Logger.log(
82
85
  LogLevel.DEBUG,
83
- `The requeste credential is not a PersonIdentificationData, requesting the credential to be presented`
86
+ "The requested credential is not a PID, requesting the credential to be presented"
84
87
  );
85
88
 
86
89
  const authzRequestEndpoint = issuerConf.authorization_endpoint;
@@ -94,61 +97,39 @@ export const getRequestedCredentialToBePresented: IssuanceApi["getRequestedCrede
94
97
  `Requesting the request object to ${authzRequestEndpoint}?${params.toString()}`
95
98
  );
96
99
 
97
- const authRequest = await fetchAuthorizationRequest({
98
- authorizeRequestUrl: `${authzRequestEndpoint}?${params.toString()}`,
99
- callbacks: {
100
- fetch: appFetch,
101
- },
102
- }).catch(sdkUnexpectedStatusCodeToIssuerError);
100
+ const requestObjectJwt = await appFetch(
101
+ `${authzRequestEndpoint}?${params.toString()}`,
102
+ { method: "GET" }
103
+ )
104
+ .then(hasStatusOrThrow(200, IssuerResponseError))
105
+ .then((res) => res.text());
103
106
 
104
107
  const parsedAuthRequest = await parseAuthorizeRequest({
105
108
  config: sdkConfigV1_3,
106
- requestObjectJwt: authRequest.requestObjectJwt,
107
- callbacks: partialCallbacks,
109
+ requestObjectJwt,
110
+ callbacks: {
111
+ verifyJwt: createVerifyJwtFromJwks(issuerConf.keys),
112
+ },
108
113
  });
109
114
 
110
115
  return mapToRequestObject(parsedAuthRequest);
111
116
  };
112
117
 
118
+ // NOTE: this function is not used in the 1.3 issuance flow. It may be removed in the future.
113
119
  export const completeUserAuthorizationWithFormPostJwtMode: IssuanceApi["completeUserAuthorizationWithFormPostJwtMode"] =
114
- async (
115
- requestObject,
116
- issuerConfig,
117
- pid,
118
- { wiaCryptoContext, pidKeyTag, appFetch = fetch }
119
- ) => {
120
+ async (requestObject, issuerConfig, pid, { appFetch = fetch }) => {
120
121
  Logger.log(
121
122
  LogLevel.DEBUG,
122
- `The requeste credential is not a PersonIdentificationData, completing the user authorization with form_post.jwt mode`
123
- );
124
-
125
- const dcqlQueryResult = await RemotePresentationFlow.evaluateDcqlQuery(
126
- requestObject.dcql_query as DcqlQuery,
127
- [[pidKeyTag, pid]]
123
+ "The requested credential is not a PID, completing the user authorization with form_post.jwt mode"
128
124
  );
129
125
 
130
- const authRequestObject = {
131
- nonce: requestObject.nonce,
132
- clientId: requestObject.client_id,
133
- responseUri: requestObject.response_uri,
134
- };
135
-
136
- const remotePresentation =
137
- await RemotePresentationFlow.prepareRemotePresentations(
138
- dcqlQueryResult,
139
- authRequestObject
140
- );
141
-
142
- const authzResponsePayload = await createAuthzResponsePayload({
143
- state: requestObject.state,
144
- remotePresentation,
145
- wiaCryptoContext,
126
+ const authzResponse = await processPidPresentationAndCreateAuthzResponse({
127
+ requestObject,
128
+ issuerConfig,
129
+ pid,
146
130
  });
147
131
 
148
- Logger.log(
149
- LogLevel.DEBUG,
150
- `Authz response payload: ${authzResponsePayload}`
151
- );
132
+ Logger.log(LogLevel.DEBUG, `Authz response: ${authzResponse}`);
152
133
 
153
134
  const issuerSigKey = issuerConfig.keys.find((key) => key.use === "sig");
154
135
  if (!issuerSigKey) {
@@ -158,13 +139,13 @@ export const completeUserAuthorizationWithFormPostJwtMode: IssuanceApi["complete
158
139
  }
159
140
 
160
141
  return sendAuthorizationResponseAndExtractCode({
161
- authorizationResponseJarm: authzResponsePayload,
142
+ authorizationResponseJarm: authzResponse.jarm.responseJwe,
162
143
  callbacks: {
163
144
  ...partialCallbacks,
164
145
  fetch: appFetch,
165
146
  },
166
147
  iss: requestObject.iss,
167
- state: requestObject.state!,
148
+ state: requestObject.state ?? "",
168
149
  presentationResponseUri: requestObject.response_uri,
169
150
  signer: {
170
151
  alg: "ES256",
@@ -174,6 +155,65 @@ export const completeUserAuthorizationWithFormPostJwtMode: IssuanceApi["complete
174
155
  });
175
156
  };
176
157
 
158
+ export const completeEaaUserAuthorizationWithQueryMode: IssuanceApi["completeEaaUserAuthorizationWithQueryMode"] =
159
+ async (
160
+ requestObject,
161
+ issuerConfig,
162
+ pid,
163
+ clientRedirectUri,
164
+ { appFetch = fetch } = {}
165
+ ) => {
166
+ Logger.log(
167
+ LogLevel.DEBUG,
168
+ "The requested credential is not a PID, completing the user authorization with query mode"
169
+ );
170
+
171
+ const authzResponse = await processPidPresentationAndCreateAuthzResponse({
172
+ requestObject,
173
+ issuerConfig,
174
+ pid,
175
+ });
176
+
177
+ Logger.log(
178
+ LogLevel.DEBUG,
179
+ `Authz response: ${JSON.stringify(authzResponse)}`
180
+ );
181
+
182
+ const { redirect_uri } = await fetchAuthorizationResponse({
183
+ authorizationResponseJarm: authzResponse.jarm.responseJwe,
184
+ presentationResponseUri: requestObject.response_uri,
185
+ callbacks: {
186
+ ...partialCallbacks,
187
+ fetch: appFetch,
188
+ },
189
+ });
190
+
191
+ if (!redirect_uri) {
192
+ const errorMessage =
193
+ "The authorization server did not return a redirect_uri to continue the authorization flow";
194
+ Logger.log(LogLevel.ERROR, errorMessage);
195
+ throw new AuthorizationError(errorMessage);
196
+ }
197
+
198
+ const response = await appFetch(redirect_uri).catch(() => null);
199
+
200
+ if (!response || !response.ok) {
201
+ const errorMessage = `An error occurred while completing the authorization flow. Ensure ${clientRedirectUri} is a valid HTTP url for redirect`;
202
+ Logger.log(LogLevel.ERROR, errorMessage);
203
+ throw new AuthorizationError(errorMessage);
204
+ }
205
+
206
+ const finalRedirectUri = response.url;
207
+
208
+ if (!finalRedirectUri || !finalRedirectUri.startsWith(clientRedirectUri)) {
209
+ const errorMessage = `The authorization server did not redirect to the provided client redirect URI. Expected: ${clientRedirectUri}, got: ${finalRedirectUri}`;
210
+ Logger.log(LogLevel.ERROR, errorMessage);
211
+ throw new AuthorizationError(errorMessage);
212
+ }
213
+
214
+ return parseAuthorizationResponse(parseUrl(finalRedirectUri).query);
215
+ };
216
+
177
217
  /**
178
218
  * Parse the authorization response and return the result which contains code, state and iss.
179
219
  * @throws {AuthorizationError} if an error occurs during the parsing process
@@ -207,45 +247,52 @@ export const parseAuthorizationResponse = (
207
247
  };
208
248
 
209
249
  /**
210
- * Creates the authorization response payload to be sent.
211
- * This payload includes the state and the VP tokens for the presented credentials.
212
- * The payload is encoded in Base64.
213
- * @param state - The state parameter from the request object (optional).
214
- * @param remotePresentation The presentations to send, each with their VP token
215
- * @returns The Base64 encoded authorization response payload.
250
+ * Utility function to process the DCQL query for PID presentation and to create the authorization response to send to the Issuer.
251
+ * @param params.requestObject - The request object containing the DCQL query
252
+ * @param params.issuerConfig - The Issuer unified configuration
253
+ * @param params.pid - The PID credential to be presented, as a tuple of [keyTag, credential]
254
+ * @returns The authorization response containing the JARM to be sent to the Issuer
216
255
  */
217
- const createAuthzResponsePayload = async ({
218
- state,
219
- remotePresentation,
220
- wiaCryptoContext,
256
+ const processPidPresentationAndCreateAuthzResponse = async ({
257
+ requestObject,
258
+ issuerConfig,
259
+ pid,
221
260
  }: {
222
- state?: string;
223
- remotePresentation: RemotePresentation;
224
- wiaCryptoContext: CryptoContext;
225
- }): Promise<string> => {
226
- const { kid } = await wiaCryptoContext.getPublicKey();
227
-
228
- return new SignJWT(wiaCryptoContext)
229
- .setProtectedHeader({
230
- typ: "jwt",
231
- kid,
232
- })
233
- .setPayload({
234
- /**
235
- * TODO [SIW-2264]: `state` coming from `requestObject` is marked as `optional`
236
- * At the moment, it is not entirely clear whether this value can indeed be omitted
237
- * and, if so, what the consequences of its absence might be.
238
- */
239
- ...(state ? { state } : {}),
240
- vp_token: remotePresentation.presentations.reduce(
241
- (vp_token, { credentialId, vpToken }) => ({
242
- ...vp_token,
243
- [credentialId]: [vpToken],
244
- }),
245
- {}
246
- ),
247
- })
248
- .setIssuedAt()
249
- .setExpirationTime("1h")
250
- .sign();
261
+ requestObject: RequestObject;
262
+ issuerConfig: IssuerConfig;
263
+ pid: [keyTag: string, credential: string];
264
+ }): Promise<CreateAuthorizationResponseResult> => {
265
+ const dcqlQueryResult = await RemotePresentationFlow.evaluateDcqlQuery(
266
+ requestObject.dcql_query as DcqlQuery,
267
+ [pid]
268
+ );
269
+
270
+ const remotePresentation =
271
+ await RemotePresentationFlow.prepareRemotePresentations(dcqlQueryResult, {
272
+ clientId: requestObject.client_id,
273
+ nonce: requestObject.nonce,
274
+ responseUri: requestObject.response_uri,
275
+ });
276
+
277
+ const vp_token = remotePresentation.presentations.reduce(
278
+ (acc, { credentialId, vpToken }) => ({ ...acc, [credentialId]: [vpToken] }),
279
+ {} as Record<string, string[]>
280
+ );
281
+
282
+ return createAuthorizationResponse({
283
+ // The SDK 1.4 config is used here in order to resolve the encryption data from the Request Object
284
+ // client_metadata, otherwise OpenID Federation clients always ignore client_metadata as per 1.3.3 specs.
285
+ config: sdkConfigV1_4,
286
+ requestObject,
287
+ rpJwks: {
288
+ jwks: { keys: issuerConfig.keys } as jsonWebKeySet,
289
+ encrypted_response_enc_values_supported:
290
+ issuerConfig.encrypted_response_enc_values_supported,
291
+ },
292
+ vp_token,
293
+ callbacks: {
294
+ encryptJwe: partialCallbacks.encryptJwe,
295
+ generateRandom: partialCallbacks.generateRandom,
296
+ },
297
+ });
251
298
  };
@@ -112,7 +112,7 @@ export const requestCredentials = async ({
112
112
  },
113
113
  clientId,
114
114
  credential_identifier: credentialIdentifier,
115
- issuerIdentifier: issuerConf.credential_issuer,
115
+ issuerIdentifier: issuerConf.credential_endpoint,
116
116
  maxBatchSize: issuerConf.credential_issuance_batch_size,
117
117
  nonce: c_nonce,
118
118
  keyAttestation: keyAttestationJwt,
@@ -261,6 +261,12 @@ export const obtainCredentialsBatch: IssuanceApi["obtainCredentialsBatch"] =
261
261
  throw new IoWalletError("Deferred issuance is not currently supported");
262
262
  }
263
263
 
264
+ if (credentialRes.credentials.length !== credentialCryptoContexts.length) {
265
+ throw new IoWalletError(
266
+ `Batch size mismatch: expected ${credentialCryptoContexts.length} credentials, but got ${credentialRes.credentials.length}`
267
+ );
268
+ }
269
+
264
270
  return credentialRes.credentials.map(({ credential }) => ({
265
271
  credential,
266
272
  format: issuerCredentialConfig!.format,
@@ -3,7 +3,8 @@ import { evaluateIssuerTrust } from "./01-evaluate-issuer-trust";
3
3
  import { startUserAuthorization } from "./02-start-user-authorization";
4
4
  import {
5
5
  continueUserAuthorizationWithMRTDPoPChallenge,
6
- completeUserAuthorizationWithQueryMode,
6
+ completePidUserAuthorizationWithQueryMode,
7
+ completeEaaUserAuthorizationWithQueryMode,
7
8
  completeUserAuthorizationWithFormPostJwtMode,
8
9
  buildAuthorizationUrl,
9
10
  getRequestedCredentialToBePresented,
@@ -20,7 +21,8 @@ export const Issuance: IssuanceApi = {
20
21
  evaluateIssuerTrust,
21
22
  startUserAuthorization,
22
23
  buildAuthorizationUrl,
23
- completeUserAuthorizationWithQueryMode,
24
+ completePidUserAuthorizationWithQueryMode,
25
+ completeEaaUserAuthorizationWithQueryMode,
24
26
  continueUserAuthorizationWithMRTDPoPChallenge,
25
27
  getRequestedCredentialToBePresented,
26
28
  completeUserAuthorizationWithFormPostJwtMode,