@pagopa/io-react-native-wallet 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/lib/commonjs/client/generated/wallet-provider.js +37 -11
  2. package/lib/commonjs/client/generated/wallet-provider.js.map +1 -1
  3. package/lib/commonjs/credential/issuance/02-get-issuer-config.js +83 -3
  4. package/lib/commonjs/credential/issuance/02-get-issuer-config.js.map +1 -1
  5. package/lib/commonjs/credential/issuance/03-start-user-authorization.js +5 -7
  6. package/lib/commonjs/credential/issuance/03-start-user-authorization.js.map +1 -1
  7. package/lib/commonjs/credential/issuance/06-obtain-credential.js +27 -10
  8. package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
  9. package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +50 -46
  10. package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
  11. package/lib/commonjs/credential/issuance/README.md +1 -1
  12. package/lib/commonjs/credential/issuance/const.js +1 -1
  13. package/lib/commonjs/credential/issuance/const.js.map +1 -1
  14. package/lib/commonjs/credential/issuance/index.js +6 -0
  15. package/lib/commonjs/credential/issuance/index.js.map +1 -1
  16. package/lib/commonjs/credential/issuance/types.js +19 -10
  17. package/lib/commonjs/credential/issuance/types.js.map +1 -1
  18. package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js +10 -3
  19. package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
  20. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +11 -4
  21. package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
  22. package/lib/commonjs/credential/presentation/08-send-authorization-response.js +3 -3
  23. package/lib/commonjs/credential/presentation/08-send-authorization-response.js.map +1 -1
  24. package/lib/commonjs/credential/presentation/types.js.map +1 -1
  25. package/lib/commonjs/entity/openid-connect/issuer/types.js +2 -2
  26. package/lib/commonjs/entity/openid-connect/issuer/types.js.map +1 -1
  27. package/lib/commonjs/entity/trust/types.js +19 -30
  28. package/lib/commonjs/entity/trust/types.js.map +1 -1
  29. package/lib/commonjs/index.js +7 -0
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/mdoc/index.js +4 -4
  32. package/lib/commonjs/mdoc/index.js.map +1 -1
  33. package/lib/commonjs/sd-jwt/index.js +2 -2
  34. package/lib/commonjs/sd-jwt/index.js.map +1 -1
  35. package/lib/commonjs/sd-jwt/types.js +1 -1
  36. package/lib/commonjs/sd-jwt/types.js.map +1 -1
  37. package/lib/commonjs/utils/credential/issuance/07-verify-and-parse-credentials-utils.js +3 -2
  38. package/lib/commonjs/utils/credential/issuance/07-verify-and-parse-credentials-utils.js.map +1 -1
  39. package/lib/commonjs/utils/pop.js +1 -1
  40. package/lib/commonjs/utils/pop.js.map +1 -1
  41. package/lib/commonjs/wallet-instance-attestation/issuing.js +11 -7
  42. package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -1
  43. package/lib/commonjs/wallet-instance-attestation/types.js +14 -19
  44. package/lib/commonjs/wallet-instance-attestation/types.js.map +1 -1
  45. package/lib/module/client/generated/wallet-provider.js +29 -7
  46. package/lib/module/client/generated/wallet-provider.js.map +1 -1
  47. package/lib/module/credential/issuance/02-get-issuer-config.js +80 -1
  48. package/lib/module/credential/issuance/02-get-issuer-config.js.map +1 -1
  49. package/lib/module/credential/issuance/03-start-user-authorization.js +5 -7
  50. package/lib/module/credential/issuance/03-start-user-authorization.js.map +1 -1
  51. package/lib/module/credential/issuance/06-obtain-credential.js +28 -11
  52. package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
  53. package/lib/module/credential/issuance/07-verify-and-parse-credential.js +50 -46
  54. package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
  55. package/lib/module/credential/issuance/README.md +1 -1
  56. package/lib/module/credential/issuance/const.js +1 -1
  57. package/lib/module/credential/issuance/const.js.map +1 -1
  58. package/lib/module/credential/issuance/index.js +2 -2
  59. package/lib/module/credential/issuance/index.js.map +1 -1
  60. package/lib/module/credential/issuance/types.js +15 -8
  61. package/lib/module/credential/issuance/types.js.map +1 -1
  62. package/lib/module/credential/presentation/07-evaluate-dcql-query.js +10 -3
  63. package/lib/module/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
  64. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +11 -4
  65. package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
  66. package/lib/module/credential/presentation/08-send-authorization-response.js +3 -3
  67. package/lib/module/credential/presentation/08-send-authorization-response.js.map +1 -1
  68. package/lib/module/credential/presentation/types.js.map +1 -1
  69. package/lib/module/entity/openid-connect/issuer/types.js +2 -2
  70. package/lib/module/entity/openid-connect/issuer/types.js.map +1 -1
  71. package/lib/module/entity/trust/types.js +19 -30
  72. package/lib/module/entity/trust/types.js.map +1 -1
  73. package/lib/module/index.js +2 -1
  74. package/lib/module/index.js.map +1 -1
  75. package/lib/module/mdoc/index.js +4 -4
  76. package/lib/module/mdoc/index.js.map +1 -1
  77. package/lib/module/sd-jwt/index.js +2 -2
  78. package/lib/module/sd-jwt/index.js.map +1 -1
  79. package/lib/module/sd-jwt/types.js +1 -1
  80. package/lib/module/sd-jwt/types.js.map +1 -1
  81. package/lib/module/utils/credential/issuance/07-verify-and-parse-credentials-utils.js +3 -2
  82. package/lib/module/utils/credential/issuance/07-verify-and-parse-credentials-utils.js.map +1 -1
  83. package/lib/module/utils/pop.js +1 -1
  84. package/lib/module/utils/pop.js.map +1 -1
  85. package/lib/module/wallet-instance-attestation/issuing.js +13 -9
  86. package/lib/module/wallet-instance-attestation/issuing.js.map +1 -1
  87. package/lib/module/wallet-instance-attestation/types.js +12 -17
  88. package/lib/module/wallet-instance-attestation/types.js.map +1 -1
  89. package/lib/typescript/client/generated/wallet-provider.d.ts +146 -17
  90. package/lib/typescript/client/generated/wallet-provider.d.ts.map +1 -1
  91. package/lib/typescript/credential/issuance/02-get-issuer-config.d.ts +15 -0
  92. package/lib/typescript/credential/issuance/02-get-issuer-config.d.ts.map +1 -1
  93. package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts.map +1 -1
  94. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts +7 -2
  95. package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -1
  96. package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
  97. package/lib/typescript/credential/issuance/const.d.ts +1 -1
  98. package/lib/typescript/credential/issuance/const.d.ts.map +1 -1
  99. package/lib/typescript/credential/issuance/index.d.ts +2 -2
  100. package/lib/typescript/credential/issuance/index.d.ts.map +1 -1
  101. package/lib/typescript/credential/issuance/types.d.ts +52 -21
  102. package/lib/typescript/credential/issuance/types.d.ts.map +1 -1
  103. package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts.map +1 -1
  104. package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -1
  105. package/lib/typescript/credential/presentation/08-send-authorization-response.d.ts +1 -1
  106. package/lib/typescript/credential/presentation/types.d.ts +4 -2
  107. package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
  108. package/lib/typescript/entity/openid-connect/issuer/types.d.ts +17 -17
  109. package/lib/typescript/entity/openid-connect/issuer/types.d.ts.map +1 -1
  110. package/lib/typescript/entity/trust/index.d.ts +150 -140
  111. package/lib/typescript/entity/trust/index.d.ts.map +1 -1
  112. package/lib/typescript/entity/trust/types.d.ts +540 -344
  113. package/lib/typescript/entity/trust/types.d.ts.map +1 -1
  114. package/lib/typescript/index.d.ts +2 -1
  115. package/lib/typescript/index.d.ts.map +1 -1
  116. package/lib/typescript/pid/sd-jwt/types.d.ts +2 -2
  117. package/lib/typescript/sd-jwt/index.d.ts +12 -12
  118. package/lib/typescript/sd-jwt/types.d.ts +14 -14
  119. package/lib/typescript/utils/credential/issuance/07-verify-and-parse-credentials-utils.d.ts.map +1 -1
  120. package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -1
  121. package/lib/typescript/wallet-instance-attestation/types.d.ts +50 -102
  122. package/lib/typescript/wallet-instance-attestation/types.d.ts.map +1 -1
  123. package/package.json +2 -2
  124. package/src/client/generated/wallet-provider.ts +39 -7
  125. package/src/credential/issuance/02-get-issuer-config.ts +117 -0
  126. package/src/credential/issuance/03-start-user-authorization.ts +7 -8
  127. package/src/credential/issuance/06-obtain-credential.ts +41 -14
  128. package/src/credential/issuance/07-verify-and-parse-credential.ts +7 -3
  129. package/src/credential/issuance/README.md +1 -1
  130. package/src/credential/issuance/const.ts +1 -0
  131. package/src/credential/issuance/index.ts +6 -1
  132. package/src/credential/issuance/types.ts +21 -8
  133. package/src/credential/presentation/07-evaluate-dcql-query.ts +15 -5
  134. package/src/credential/presentation/07-evaluate-input-descriptor.ts +21 -4
  135. package/src/credential/presentation/08-send-authorization-response.ts +3 -3
  136. package/src/credential/presentation/types.ts +3 -0
  137. package/src/entity/openid-connect/issuer/types.ts +2 -1
  138. package/src/entity/trust/types.ts +22 -20
  139. package/src/index.ts +2 -0
  140. package/src/mdoc/index.ts +4 -4
  141. package/src/sd-jwt/index.ts +2 -2
  142. package/src/sd-jwt/types.ts +1 -1
  143. package/src/utils/credential/issuance/07-verify-and-parse-credentials-utils.ts +3 -2
  144. package/src/utils/pop.ts +1 -1
  145. package/src/wallet-instance-attestation/issuing.ts +14 -8
  146. package/src/wallet-instance-attestation/types.ts +16 -22
@@ -1,5 +1,11 @@
1
1
  import z from "zod";
2
2
 
3
+ export type ApplicationInfo = z.infer<typeof ApplicationInfo>;
4
+ export const ApplicationInfo = z.object({
5
+ name: z.string(),
6
+ version: z.string(),
7
+ });
8
+
3
9
  export type NonceDetailView = z.infer<typeof NonceDetailView>;
4
10
  export const NonceDetailView = z.object({
5
11
  nonce: z.string(),
@@ -10,6 +16,16 @@ export const WalletAttestationView = z.object({
10
16
  wallet_attestation: z.string(),
11
17
  });
12
18
 
19
+ export type WalletAttestationsView = z.infer<typeof WalletAttestationsView>;
20
+ export const WalletAttestationsView = z.object({
21
+ wallet_attestations: z.array(
22
+ z.object({
23
+ format: z.union([z.literal("jwt"), z.literal("dc+sd-jwt")]),
24
+ wallet_attestation: z.string(),
25
+ }),
26
+ ),
27
+ });
28
+
13
29
  export type CreateWalletInstanceBody = z.infer<typeof CreateWalletInstanceBody>;
14
30
  export const CreateWalletInstanceBody = z.object({
15
31
  challenge: z.string(),
@@ -23,13 +39,9 @@ export const CreateWalletAttestationBody = z.object({
23
39
  assertion: z.string(),
24
40
  });
25
41
 
26
- export type ProblemDetail = z.infer<typeof ProblemDetail>;
27
- export const ProblemDetail = z.object({
28
- type: z.string().optional(),
29
- title: z.string().optional(),
30
- status: z.number().optional(),
31
- detail: z.string().optional(),
32
- instance: z.string().optional(),
42
+ export type CreateWalletAttestationV2Body = z.infer<typeof CreateWalletAttestationV2Body>;
43
+ export const CreateWalletAttestationV2Body = z.object({
44
+ assertion: z.string(),
33
45
  });
34
46
 
35
47
  export type SetWalletInstanceStatusBody = z.infer<typeof SetWalletInstanceStatusBody>;
@@ -51,6 +63,15 @@ export const WalletInstanceData = z.object({
51
63
  revocation_reason: z.union([RevocationReason, z.undefined()]).optional(),
52
64
  });
53
65
 
66
+ export type ProblemDetail = z.infer<typeof ProblemDetail>;
67
+ export const ProblemDetail = z.object({
68
+ type: z.string().optional(),
69
+ title: z.string().optional(),
70
+ status: z.number().optional(),
71
+ detail: z.string().optional(),
72
+ instance: z.string().optional(),
73
+ });
74
+
54
75
  export type get_GetNonce = typeof get_GetNonce;
55
76
  export const get_GetNonce = {
56
77
  method: z.literal("GET"),
@@ -104,6 +125,16 @@ export const post_CreateWalletAttestation = {
104
125
  response: WalletAttestationView,
105
126
  };
106
127
 
128
+ export type post_CreateWalletAttestationV2 = typeof post_CreateWalletAttestationV2;
129
+ export const post_CreateWalletAttestationV2 = {
130
+ method: z.literal("POST"),
131
+ path: z.literal("/wallet-attestations"),
132
+ parameters: z.object({
133
+ body: CreateWalletAttestationV2Body,
134
+ }),
135
+ response: WalletAttestationsView,
136
+ };
137
+
107
138
  // <EndpointByMethod>
108
139
  export const EndpointByMethod = {
109
140
  get: {
@@ -113,6 +144,7 @@ export const EndpointByMethod = {
113
144
  post: {
114
145
  "/wallet-instances": post_CreateWalletInstance,
115
146
  "/token": post_CreateWalletAttestation,
147
+ "/wallet-attestations": post_CreateWalletAttestationV2,
116
148
  },
117
149
  put: {
118
150
  "/wallet-instances/{id}/status": put_SetWalletInstanceStatus,
@@ -3,6 +3,7 @@ import type { Out } from "../../utils/misc";
3
3
  import type { JWK } from "src/utils/jwk";
4
4
  import { getCredentialIssuerMetadata } from "../../entity/openid-connect/issuer";
5
5
  import type { CredentialConfigurationSupported } from "../../entity/openid-connect/issuer/types";
6
+ import { getCredentialIssuerEntityConfiguration } from "@pagopa/io-react-native-wallet";
6
7
 
7
8
  export type GetIssuerConfig = (
8
9
  issuerUrl: Out<StartFlow>["issuerUrl"],
@@ -21,12 +22,16 @@ export type IssuerConfig = {
21
22
  pushed_authorization_request_endpoint: string;
22
23
  authorization_endpoint: string;
23
24
  token_endpoint: string;
25
+ nonce_endpoint?: string;
24
26
  credential_endpoint: string;
27
+ issuer: string;
25
28
  keys: Array<JWK>;
26
29
  };
27
30
 
28
31
  /**
29
32
  * WARNING: This function must be called after {@link startFlow}. The next function to be called is {@link startUserAuthorization}.
33
+ * WARNING: This function extracts the {@link IssuerConfig} from the OpenID Connect endpoint. For the OpenID Federation variant, use {@link getIssuerConfigOIDFED}.
34
+ * WARNING: The variants should not be used in conjunction.
30
35
  * Get the Issuer's configuration from the Issuer's metadata.
31
36
  * Currently it only supports a mixed configuration based on OpenID Connect partial implementation.
32
37
  * @param issuerUrl The base url of the Issuer returned by {@link startFlow}
@@ -44,6 +49,27 @@ export const getIssuerConfig: GetIssuerConfig = async (
44
49
  return credentialIssuerRationalization(res);
45
50
  };
46
51
 
52
+ /**
53
+ * WARNING: This function must be called after {@link startFlow}. The next function to be called is {@link startUserAuthorization}.
54
+ * WARNING: This function extracts the {@link IssuerConfig} from the OpenID Federation EC. For the OpenID Connect variant, use {@link getIssuerConfig}.
55
+ * WARNING: The variants should not be used in conjunction.
56
+ * Get the Issuer's configuration from the Issuer's metadata fetched from the OpenID Federation system.
57
+ * Currently it only supports a mixed configuration based on OpenID Federation partial implementation.
58
+ * @param issuerUrl The base url of the Issuer returned by {@link startFlow}
59
+ * @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
60
+ * @returns The Issuer's configuration
61
+ */
62
+ export const getIssuerConfigOIDFED: GetIssuerConfig = async (
63
+ issuerUrl,
64
+ context = {}
65
+ ): ReturnType<GetIssuerConfig> => {
66
+ const res = await getCredentialIssuerEntityConfiguration(issuerUrl, {
67
+ appFetch: context.appFetch,
68
+ });
69
+
70
+ return credentialIssuerRationalizationOIDFED(res);
71
+ };
72
+
47
73
  /**
48
74
  * Rationalize the issuer's metadata to the issuer's configuration which is then used in our flows to interact with the issuer.
49
75
  * @param issuerMetadata - The issuer's metadata
@@ -62,6 +88,97 @@ const credentialIssuerRationalization = (
62
88
  token_endpoint: issuerMetadata.token_endpoint,
63
89
  credential_endpoint: issuerMetadata.credential_endpoint,
64
90
  keys: issuerMetadata.jwks.keys,
91
+ issuer: issuerMetadata.authorization_endpoint,
92
+ },
93
+ };
94
+ };
95
+
96
+ /**
97
+ * Rationalize the issuer's metadata taken from OpenID Federation to the issuer's configuration which is then used in our flows to interact with the issuer.
98
+ * @param issuerMetadata - The issuer's metadata
99
+ * @returns the isssuer configuration to be used later in our flows
100
+ */
101
+ const credentialIssuerRationalizationOIDFED = (
102
+ issuerMetadata: Awaited<
103
+ ReturnType<typeof getCredentialIssuerEntityConfiguration>
104
+ >
105
+ ): Awaited<ReturnType<GetIssuerConfig>> => {
106
+ const adapted_credential_configurations_supported: CredentialConfigurationSupported =
107
+ Object.fromEntries(
108
+ Object.entries(
109
+ issuerMetadata.payload.metadata.openid_credential_issuer
110
+ .credential_configurations_supported
111
+ ).map(([key, config]) => {
112
+ const claimsRaw = config.claims;
113
+ // we need to evaluate how claims is in oder to support Federation and OID4VCI
114
+ // claim structure is different in both case
115
+ let claims: CredentialConfigurationSupported[string]["claims"];
116
+
117
+ if (
118
+ claimsRaw &&
119
+ typeof Object.values(claimsRaw)[0] === "object" &&
120
+ "mandatory" in Object.values(claimsRaw)[0]!
121
+ ) {
122
+ // claims is Record<string, { mandatory: boolean; display: Display[] }>
123
+ claims = Object.fromEntries(
124
+ Object.entries(claimsRaw).map(([, v]) => [
125
+ [v.path[0]],
126
+ {
127
+ mandatory: true,
128
+ display: v.display,
129
+ },
130
+ ])
131
+ );
132
+ } else {
133
+ // claims is Record<string, Record<string, { mandatory; display }>>
134
+ claims = Object.fromEntries(
135
+ Object.entries(claimsRaw).map(([k, inner]) => [
136
+ [k],
137
+ Object.fromEntries(
138
+ Object.entries(inner).map(([innerK, v]: any) => [
139
+ [innerK],
140
+ {
141
+ mandatory: v.mandatory,
142
+ display: v.display,
143
+ },
144
+ ])
145
+ ),
146
+ ])
147
+ );
148
+ }
149
+ const newConfig: CredentialConfigurationSupported[string] = {
150
+ ...config,
151
+ claims,
152
+ // cryptographic_suites_supported have been renamed credential_signing_alg_values_supported.
153
+ // We mantain it for Potential compatibility
154
+ cryptographic_suites_supported:
155
+ config.credential_signing_alg_values_supported!,
156
+ };
157
+
158
+ return [key, newConfig];
159
+ })
160
+ );
161
+
162
+ return {
163
+ issuerConf: {
164
+ credential_configurations_supported:
165
+ adapted_credential_configurations_supported,
166
+ pushed_authorization_request_endpoint:
167
+ issuerMetadata.payload.metadata.oauth_authorization_server
168
+ .pushed_authorization_request_endpoint,
169
+ authorization_endpoint:
170
+ issuerMetadata.payload.metadata.oauth_authorization_server
171
+ .authorization_endpoint,
172
+ token_endpoint:
173
+ issuerMetadata.payload.metadata.oauth_authorization_server
174
+ .token_endpoint,
175
+ credential_endpoint:
176
+ issuerMetadata.payload.metadata.openid_credential_issuer
177
+ .credential_endpoint,
178
+ keys: issuerMetadata.payload.metadata.openid_credential_issuer.jwks.keys,
179
+ issuer: issuerMetadata.payload.metadata.oauth_authorization_server.issuer,
180
+ nonce_endpoint:
181
+ issuerMetadata.payload.metadata.openid_credential_issuer.nonce_endpoint,
65
182
  },
66
183
  };
67
184
  };
@@ -39,18 +39,17 @@ const selectCredentialDefinition = (
39
39
  const credential_configurations_supported =
40
40
  issuerConf.credential_configurations_supported;
41
41
 
42
- const credential = credential_configurations_supported[credentialType];
42
+ const [result] = Object.keys(credential_configurations_supported)
43
+ .filter((e) => e.includes(credentialType))
44
+ .map(() => ({
45
+ credential_configuration_id: credentialType,
46
+ type: "openid_credential" as const,
47
+ }));
43
48
 
44
- if (!credential) {
49
+ if (!result) {
45
50
  throw new Error(`No credential support the type '${credentialType}'`);
46
51
  }
47
52
 
48
- const result = {
49
- credential_configuration_id: credentialType,
50
- format: credential.format,
51
- type: "openid_credential" as const,
52
- };
53
-
54
53
  return result;
55
54
  };
56
55
 
@@ -14,7 +14,7 @@ import {
14
14
  UnexpectedStatusCodeError,
15
15
  ValidationFailed,
16
16
  } from "../../utils/errors";
17
- import { CredentialResponse } from "./types";
17
+ import { CredentialResponse, NonceResponse } from "./types";
18
18
  import { createDPopToken } from "../../utils/dpop";
19
19
  import uuid from "react-native-uuid";
20
20
 
@@ -22,13 +22,16 @@ export type ObtainCredential = (
22
22
  issuerConf: Out<GetIssuerConfig>["issuerConf"],
23
23
  accessToken: Out<AuthorizeAccess>["accessToken"],
24
24
  clientId: Out<StartUserAuthorization>["clientId"],
25
- credentialDefinition: Out<StartUserAuthorization>["credentialDefinition"],
25
+ credentialDefinition: {
26
+ credential_configuration_id: string;
27
+ credential_identifier?: string;
28
+ },
26
29
  context: {
27
30
  dPopCryptoContext: CryptoContext;
28
31
  credentialCryptoContext: CryptoContext;
29
32
  appFetch?: GlobalFetch["fetch"];
30
33
  }
31
- ) => Promise<CredentialResponse>;
34
+ ) => Promise<CredentialResponse["credentials"][number] & { format: string }>;
32
35
 
33
36
  export const createNonceProof = async (
34
37
  nonce: string,
@@ -82,6 +85,25 @@ export const obtainCredential: ObtainCredential = async (
82
85
  } = context;
83
86
 
84
87
  const credentialUrl = issuerConf.credential_endpoint;
88
+ const issuerUrl = issuerConf.issuer;
89
+ const nonceUrl = issuerConf.nonce_endpoint;
90
+
91
+ // Fetch the nonce from the Credential Issuer
92
+ const { c_nonce } = nonceUrl
93
+ ? await appFetch(nonceUrl, {
94
+ method: "POST",
95
+ headers: { "Content-Type": "application/json" },
96
+ })
97
+ .then(hasStatusOrThrow(200))
98
+ .then((res) => res.json())
99
+ .then((body) => NonceResponse.parse(body))
100
+ : accessToken;
101
+ if (!c_nonce) {
102
+ throw new ValidationFailed({
103
+ message:
104
+ "Nonce Endpoint not found or access token does not contain the c_nonce",
105
+ });
106
+ }
85
107
 
86
108
  /**
87
109
  * JWT proof token to bind the request nonce to the key that will bind the holder User with the Credential
@@ -89,17 +111,22 @@ export const obtainCredential: ObtainCredential = async (
89
111
  * @see https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-proof-types
90
112
  */
91
113
  const signedNonceProof = await createNonceProof(
92
- accessToken.c_nonce,
114
+ c_nonce,
93
115
  clientId,
94
- credentialUrl,
116
+ issuerUrl,
95
117
  credentialCryptoContext
96
118
  );
97
119
 
120
+ // Validation of accessTokenResponse.authorization_details if contain credentialDefinition
98
121
  const containsCredentialDefinition = accessToken.authorization_details.some(
99
- (detail) =>
100
- detail.credential_configuration_id ===
122
+ (c) =>
123
+ c.credential_configuration_id ===
101
124
  credentialDefinition.credential_configuration_id &&
102
- detail.type === credentialDefinition.type
125
+ (credentialDefinition.credential_identifier
126
+ ? c.credential_identifiers.includes(
127
+ credentialDefinition.credential_identifier
128
+ )
129
+ : true)
103
130
  );
104
131
 
105
132
  if (!containsCredentialDefinition) {
@@ -131,10 +158,7 @@ export const obtainCredential: ObtainCredential = async (
131
158
 
132
159
  /** The credential request body */
133
160
  const credentialRequestFormBody = {
134
- ...(format === "mso_mdoc"
135
- ? { doctype: credentialDefinition.credential_configuration_id }
136
- : { vct: credentialDefinition.credential_configuration_id }),
137
- format,
161
+ credential_identifier: credentialDefinition.credential_configuration_id,
138
162
  proof: {
139
163
  jwt: signedNonceProof,
140
164
  proof_type: "jwt",
@@ -171,8 +195,11 @@ export const obtainCredential: ObtainCredential = async (
171
195
  });
172
196
  }
173
197
 
174
- /* temporary base64 parsing for the "mso_mdoc" format until the credential submission with this format is fixed. */
175
- return credentialRes.data;
198
+ // We support only one credential for now
199
+ return {
200
+ format,
201
+ ...credentialRes.data.credentials.at(0)!,
202
+ };
176
203
  };
177
204
 
178
205
  /**
@@ -72,7 +72,9 @@ export const parseCredentialSdJwt = (
72
72
  ignoreMissingAttributes: boolean = false,
73
73
  includeUndefinedAttributes: boolean = false
74
74
  ): ParsedCredential => {
75
- const credentialSubject = credentials_supported[sdJwt.payload.vct];
75
+ const credentialSubject = Object.entries(credentials_supported).find(
76
+ ([, vl]) => vl.vct === sdJwt.payload.vct
77
+ )?.[1];
76
78
 
77
79
  if (!credentialSubject) {
78
80
  throw new IoWalletError("Credential type not supported by the issuer");
@@ -388,7 +390,9 @@ type WithFormat<Format extends Parameters<VerifyAndParseCredential>[2]> = (
388
390
  _4: Parameters<VerifyAndParseCredential>[4]
389
391
  ) => ReturnType<VerifyAndParseCredential>;
390
392
 
391
- const verifyAndParseCredentialSdJwt: WithFormat<"vc+sd-jwt"> = async (
393
+ const verifyAndParseCredentialSdJwt: WithFormat<
394
+ "vc+sd-jwt" | "dc+sd-jwt"
395
+ > = async (
392
396
  issuerConf,
393
397
  credential,
394
398
  _,
@@ -485,7 +489,7 @@ export const verifyAndParseCredential: VerifyAndParseCredential = async (
485
489
  credentialType,
486
490
  context
487
491
  ) => {
488
- if (format === "vc+sd-jwt") {
492
+ if (format === "vc+sd-jwt" || format === "dc+sd-jwt") {
489
493
  return verifyAndParseCredentialSdJwt(
490
494
  issuerConf,
491
495
  credential,
@@ -248,7 +248,7 @@ const credentialCryptoContext = createCryptoContextFor(credentialKeyTag);
248
248
  // Start the issuance flow
249
249
  const startFlow: Credential.Issuance.StartFlow = () => ({
250
250
  issuerUrl: WALLET_EID_PROVIDER_BASE_URL,
251
- credentialType: "urn:eu.europa.ec.eudi:pid:1",
251
+ credentialType: "dc_sd_jwt_PersonIdentificationData",
252
252
  appFetch,
253
253
  });
254
254
 
@@ -7,5 +7,6 @@ export type SupportedCredentialFormat = z.infer<
7
7
  >;
8
8
  export const SupportedCredentialFormat = z.union([
9
9
  z.literal("vc+sd-jwt"),
10
+ z.literal("dc+sd-jwt"),
10
11
  z.literal("mso_mdoc"),
11
12
  ]);
@@ -1,5 +1,9 @@
1
1
  import { type StartFlow } from "./01-start-flow";
2
- import { getIssuerConfig, type GetIssuerConfig } from "./02-get-issuer-config";
2
+ import {
3
+ getIssuerConfig,
4
+ getIssuerConfigOIDFED,
5
+ type GetIssuerConfig,
6
+ } from "./02-get-issuer-config";
3
7
  import {
4
8
  startUserAuthorization,
5
9
  type StartUserAuthorization,
@@ -28,6 +32,7 @@ import * as Errors from "./errors";
28
32
 
29
33
  export {
30
34
  getIssuerConfig,
35
+ getIssuerConfigOIDFED,
31
36
  startUserAuthorization,
32
37
  buildAuthorizationUrl,
33
38
  completeUserAuthorizationWithQueryMode,
@@ -1,14 +1,20 @@
1
- import { AuthorizationDetail } from "../../utils/par";
2
1
  import * as z from "zod";
3
- import { SupportedCredentialFormat } from "./const";
2
+
3
+ export type AuthorizationDetail = z.infer<typeof AuthorizationDetail>;
4
+ export const AuthorizationDetail = z.object({
5
+ type: z.literal("openid_credential"),
6
+ credential_configuration_id: z.string(),
7
+ credential_identifiers: z.array(z.string()),
8
+ });
4
9
 
5
10
  export type TokenResponse = z.infer<typeof TokenResponse>;
6
11
 
7
12
  export const TokenResponse = z.object({
8
13
  access_token: z.string(),
9
14
  authorization_details: z.array(AuthorizationDetail),
10
- c_nonce: z.string(),
11
- c_nonce_expires_in: z.number(),
15
+ // IT Wallet 1.0 remove c_nonce from token, mantain optional for compatibility with Potential
16
+ c_nonce: z.string().optional(),
17
+ c_nonce_expires_in: z.number().optional(),
12
18
  expires_in: z.number(),
13
19
  token_type: z.string(),
14
20
  });
@@ -16,10 +22,12 @@ export const TokenResponse = z.object({
16
22
  export type CredentialResponse = z.infer<typeof CredentialResponse>;
17
23
 
18
24
  export const CredentialResponse = z.object({
19
- c_nonce: z.string(),
20
- c_nonce_expires_in: z.number(),
21
- credential: z.string(),
22
- format: SupportedCredentialFormat,
25
+ credentials: z.array(
26
+ z.object({
27
+ credential: z.string(),
28
+ })
29
+ ),
30
+ notification_id: z.string().optional(),
23
31
  });
24
32
 
25
33
  /**
@@ -30,3 +38,8 @@ export const ResponseUriResultShape = z.object({
30
38
  });
31
39
 
32
40
  export type ResponseMode = "query" | "form_post.jwt";
41
+
42
+ export type NonceResponse = z.infer<typeof NonceResponse>;
43
+ export const NonceResponse = z.object({
44
+ c_nonce: z.string(),
45
+ });
@@ -12,6 +12,7 @@ import { ValidationFailed } from "../../utils/errors";
12
12
  import { CredentialNotFoundError } from "./errors";
13
13
  import type { CredentialFormat, EvaluatedDisclosure } from "./types";
14
14
  import { CBOR } from "@pagopa/io-react-native-cbor";
15
+ import { b64utob64 } from "jsrsasign";
15
16
 
16
17
  /**
17
18
  * The purpose for the credential request by the RP.
@@ -80,7 +81,7 @@ const mapCredentialsMdocToObj = async (
80
81
  return await Promise.all(
81
82
  credentialsMdoc?.map(async ([type, _, credential]) => {
82
83
  const issuerSigned = credential
83
- ? await CBOR.decodeIssuerSigned(credential)
84
+ ? await CBOR.decodeIssuerSigned(b64utob64(credential))
84
85
  : undefined;
85
86
  if (!issuerSigned) {
86
87
  throw new CredentialNotFoundError(
@@ -151,15 +152,24 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = async (
151
152
  required: Boolean(credentialSet.required),
152
153
  }));
153
154
 
154
- if (match.output.credential_format === "vc+sd-jwt") {
155
+ if (
156
+ match.output.credential_format === "vc+sd-jwt" ||
157
+ match.output.credential_format === "dc+sd-jwt"
158
+ ) {
155
159
  const { vct, claims } = match.output;
156
160
 
157
161
  const [, keyTag, credential] = credentialsSdJwt.find(
158
162
  ([type]) => type === vct
159
163
  )!;
160
- const requiredDisclosures = Object.values(
161
- claims
162
- ) as EvaluatedDisclosure[];
164
+
165
+ const requiredDisclosures = Object.values(claims).map((item) => {
166
+ const [_, name, value] = item as [string, string, string];
167
+ return {
168
+ name,
169
+ value,
170
+ };
171
+ }) as EvaluatedDisclosure[];
172
+
163
173
  return {
164
174
  id,
165
175
  vct,
@@ -5,6 +5,7 @@ import { JSONPath } from "jsonpath-plus";
5
5
  import { MissingDataError, CredentialNotFoundError } from "./errors";
6
6
  import Ajv from "ajv";
7
7
  import { CBOR } from "@pagopa/io-react-native-cbor";
8
+ import { b64utob64 } from "jsrsasign";
8
9
 
9
10
  const ajv = new Ajv({ allErrors: true });
10
11
 
@@ -253,6 +254,12 @@ export const evaluateInputDescriptorForMdoc: EvaluateInputDescriptorMdoc = (
253
254
  );
254
255
  }
255
256
 
257
+ if (requiredDisclosures.length === 0 && optionalDisclosures.length === 0) {
258
+ throw new MissingDataError(
259
+ "Credential validation failed: No required fields were requested and no optional field has been requested or found."
260
+ );
261
+ }
262
+
256
263
  return {
257
264
  requiredDisclosures,
258
265
  optionalDisclosures,
@@ -348,6 +355,12 @@ export const evaluateInputDescriptorForSdJwt4VC: EvaluateInputDescriptorSdJwt4VC
348
355
  );
349
356
  }
350
357
 
358
+ if (requiredDisclosures.length === 0 && optionalDisclosures.length === 0) {
359
+ throw new MissingDataError(
360
+ "Credential validation failed: No required fields were requested and no optional field has been requested or found."
361
+ );
362
+ }
363
+
351
364
  return {
352
365
  requiredDisclosures,
353
366
  optionalDisclosures,
@@ -465,7 +478,9 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
465
478
  const decodedMdocCredentials =
466
479
  (await Promise.all(
467
480
  credentialsMdoc?.map(async ([, keyTag, credential]) => {
468
- const issuerSigned = await CBOR.decodeIssuerSigned(credential);
481
+ const issuerSigned = await CBOR.decodeIssuerSigned(
482
+ b64utob64(credential)
483
+ );
469
484
  if (!issuerSigned) {
470
485
  throw new CredentialNotFoundError(
471
486
  "mso_mdoc credential is not present."
@@ -483,7 +498,6 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
483
498
  "mso_mdoc credential is not supported."
484
499
  );
485
500
  }
486
-
487
501
  const { matchedEvaluation, matchedKeyTag, matchedCredential } =
488
502
  findCredentialMDoc(descriptor, decodedMdocCredentials);
489
503
 
@@ -495,10 +509,13 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
495
509
  };
496
510
  }
497
511
 
498
- if (descriptor.format?.["vc+sd-jwt"]) {
512
+ if (
513
+ descriptor.format?.["vc+sd-jwt"] ||
514
+ descriptor.format?.["dc+sd-jwt"]
515
+ ) {
499
516
  if (!decodedSdJwtCredentials.length) {
500
517
  throw new CredentialNotFoundError(
501
- "vc+sd-jwt credential is not supported."
518
+ "vc+sd-jwt or dc+sd-jwt credential is not supported."
502
519
  );
503
520
  }
504
521
 
@@ -338,7 +338,7 @@ export const sendAuthorizationResponseDcql: SendAuthorizationResponseDcql =
338
338
  * Prepares remote presentations for a set of credentials.
339
339
  *
340
340
  * For each credential, this function:
341
- * - Validates the credential format (currently supports 'mso_mdoc' and 'vc+sd-jwt').
341
+ * - Validates the credential format (currently supports 'mso_mdoc', 'vc+sd-jwt' or 'dc+sd-jwt').
342
342
  * - Generates a verifiable presentation token (vpToken) using the appropriate method.
343
343
  * - For ISO 18013-7, generates a special nonce with minimum entropy of 16.
344
344
  *
@@ -381,7 +381,7 @@ export const prepareRemotePresentations: PrepareRemotePresentations = async (
381
381
  };
382
382
  }
383
383
 
384
- if (format === "vc+sd-jwt") {
384
+ if (format === "vc+sd-jwt" || format === "dc+sd-jwt") {
385
385
  const { vp_token } = await prepareVpToken(
386
386
  authRequestObject.nonce,
387
387
  authRequestObject.clientId,
@@ -396,7 +396,7 @@ export const prepareRemotePresentations: PrepareRemotePresentations = async (
396
396
  requestedClaims: [...item.requestedClaims.map(({ name }) => name)],
397
397
  credentialId: credentialInputId,
398
398
  vpToken: vp_token,
399
- format: "vc+sd-jwt",
399
+ format,
400
400
  };
401
401
  }
402
402
 
@@ -13,6 +13,9 @@ export type CredentialFormat =
13
13
  | {
14
14
  format: "vc+sd-jwt";
15
15
  }
16
+ | {
17
+ format: "dc+sd-jwt";
18
+ }
16
19
  | {
17
20
  format: "mso_mdoc";
18
21
  doctype: string;
@@ -24,6 +24,7 @@ export const CredentialClaimDisplay = z.object({
24
24
 
25
25
  export const CredentialFormat = z.union([
26
26
  z.literal("vc+sd-jwt"),
27
+ z.literal("dc+sd-jwt"),
27
28
  z.literal("mso_mdoc"),
28
29
  ]);
29
30
 
@@ -41,7 +42,7 @@ export type CredentialConfigurationSupported = z.infer<
41
42
  >;
42
43
  export const CredentialConfigurationSupported = z.record(
43
44
  z.object({
44
- cryptographic_suites_supported: z.array(z.string()),
45
+ cryptographic_suites_supported: z.array(z.string()).optional(),
45
46
  vct: z.string().optional(),
46
47
  scope: z.string().optional(),
47
48
  cryptographic_binding_methods_supported: z.array(z.string()),