@pagopa/io-react-native-wallet 2.0.0-next.3 → 2.0.0-next.4
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.
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +75 -57
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/commonjs/credential/issuance/README.md +45 -34
- package/lib/commonjs/credential/issuance/types.js +1 -0
- package/lib/commonjs/credential/issuance/types.js.map +1 -1
- package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js +6 -13
- package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
- package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +7 -8
- package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
- package/lib/commonjs/credential/presentation/types.js +1 -1
- package/lib/commonjs/credential/presentation/types.js.map +1 -1
- package/lib/commonjs/sd-jwt/index.js +6 -1
- package/lib/commonjs/sd-jwt/index.js.map +1 -1
- package/lib/commonjs/sd-jwt/types.js +25 -9
- package/lib/commonjs/sd-jwt/types.js.map +1 -1
- package/lib/commonjs/wallet-instance-attestation/types.js +1 -2
- package/lib/commonjs/wallet-instance-attestation/types.js.map +1 -1
- package/lib/module/credential/issuance/04-complete-user-authorization.js +76 -58
- package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/module/credential/issuance/README.md +45 -34
- package/lib/module/credential/issuance/types.js +1 -0
- package/lib/module/credential/issuance/types.js.map +1 -1
- package/lib/module/credential/presentation/07-evaluate-dcql-query.js +6 -13
- package/lib/module/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
- package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +7 -8
- package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
- package/lib/module/credential/presentation/types.js +1 -1
- package/lib/module/credential/presentation/types.js.map +1 -1
- package/lib/module/sd-jwt/index.js +6 -1
- package/lib/module/sd-jwt/index.js.map +1 -1
- package/lib/module/sd-jwt/types.js +25 -9
- package/lib/module/sd-jwt/types.js.map +1 -1
- package/lib/module/wallet-instance-attestation/types.js +1 -2
- package/lib/module/wallet-instance-attestation/types.js.map +1 -1
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +7 -14
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/types.d.ts +3 -0
- package/lib/typescript/credential/issuance/types.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/01-start-flow.d.ts +2 -2
- package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts +4 -3
- package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts +9 -5
- package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/types.d.ts +3 -4
- package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
- package/lib/typescript/credential/status/types.d.ts +4 -4
- package/lib/typescript/sd-jwt/index.d.ts +68 -40
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/types.d.ts +97 -46
- package/lib/typescript/sd-jwt/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/credential/issuance/04-complete-user-authorization.ts +79 -85
- package/src/credential/issuance/06-obtain-credential.ts +4 -1
- package/src/credential/issuance/README.md +45 -34
- package/src/credential/issuance/types.ts +1 -0
- package/src/credential/presentation/07-evaluate-dcql-query.ts +16 -17
- package/src/credential/presentation/07-evaluate-input-descriptor.ts +16 -13
- package/src/credential/presentation/types.ts +1 -2
- package/src/sd-jwt/index.ts +5 -1
- package/src/sd-jwt/types.ts +24 -10
- package/src/wallet-instance-attestation/types.ts +1 -1
@@ -2,9 +2,9 @@ import { DcqlQuery, DcqlError, DcqlQueryResult } from "dcql";
|
|
2
2
|
import { isValiError } from "valibot";
|
3
3
|
import { decode, prepareVpToken } from "../../sd-jwt";
|
4
4
|
import type { Disclosure } from "../../sd-jwt/types";
|
5
|
-
import { createCryptoContextFor } from "../../utils/crypto";
|
6
5
|
import type { RemotePresentation } from "./types";
|
7
6
|
import { CredentialsNotFoundError, type NotFoundDetail } from "./errors";
|
7
|
+
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
8
8
|
|
9
9
|
/**
|
10
10
|
* The purpose for the credential request by the RP.
|
@@ -15,13 +15,13 @@ type CredentialPurpose = {
|
|
15
15
|
};
|
16
16
|
|
17
17
|
export type EvaluateDcqlQuery = (
|
18
|
-
credentialsSdJwt: [
|
18
|
+
credentialsSdJwt: [CryptoContext, string /* credential */][],
|
19
19
|
query: DcqlQuery.Input
|
20
20
|
) => {
|
21
21
|
id: string;
|
22
22
|
vct: string;
|
23
23
|
credential: string;
|
24
|
-
|
24
|
+
cryptoContext: CryptoContext;
|
25
25
|
requiredDisclosures: Disclosure[];
|
26
26
|
purposes: CredentialPurpose[];
|
27
27
|
}[];
|
@@ -30,7 +30,7 @@ export type PrepareRemotePresentations = (
|
|
30
30
|
credentials: {
|
31
31
|
id: string;
|
32
32
|
credential: string;
|
33
|
-
|
33
|
+
cryptoContext: CryptoContext;
|
34
34
|
requestedClaims: string[];
|
35
35
|
}[],
|
36
36
|
nonce: string,
|
@@ -55,11 +55,6 @@ const mapCredentialToObject = (jwt: string) => {
|
|
55
55
|
const { sdJwt, disclosures } = decode(jwt);
|
56
56
|
const credentialFormat = sdJwt.header.typ;
|
57
57
|
|
58
|
-
// TODO [SIW-2082]: support MDOC credentials
|
59
|
-
if (credentialFormat !== "dc+sd-jwt") {
|
60
|
-
throw new Error(`Unsupported credential format: ${credentialFormat}`);
|
61
|
-
}
|
62
|
-
|
63
58
|
return {
|
64
59
|
vct: sdJwt.payload.vct,
|
65
60
|
credential_format: credentialFormat,
|
@@ -100,7 +95,10 @@ const extractMissingCredentials = (
|
|
100
95
|
): NotFoundDetail[] => {
|
101
96
|
return getDcqlQueryFailedMatches(queryResult).map(([id]) => {
|
102
97
|
const credential = originalQuery.credentials.find((c) => c.id === id);
|
103
|
-
if (
|
98
|
+
if (
|
99
|
+
credential?.format !== "dc+sd-jwt" &&
|
100
|
+
credential?.format !== "vc+sd-jwt"
|
101
|
+
) {
|
104
102
|
throw new Error("Unsupported format"); // TODO [SIW-2082]: support MDOC credentials
|
105
103
|
}
|
106
104
|
return { id, vctValues: credential.meta?.vct_values };
|
@@ -114,7 +112,6 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = (
|
|
114
112
|
const credentials = credentialsSdJwt.map(([, credential]) =>
|
115
113
|
mapCredentialToObject(credential)
|
116
114
|
);
|
117
|
-
|
118
115
|
try {
|
119
116
|
// Validate the query
|
120
117
|
const parsedQuery = DcqlQuery.parse(query);
|
@@ -131,11 +128,14 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = (
|
|
131
128
|
// Build an object vct:credentialJwt to map matched credentials to their JWT
|
132
129
|
const credentialsSdJwtByVct = credentials.reduce(
|
133
130
|
(acc, c, i) => ({ ...acc, [c.vct]: credentialsSdJwt[i]! }),
|
134
|
-
{} as Record<string, [
|
131
|
+
{} as Record<string, [CryptoContext, string /* credential */]>
|
135
132
|
);
|
136
133
|
|
137
134
|
return getDcqlQueryMatches(queryResult).map(([id, match]) => {
|
138
|
-
if (
|
135
|
+
if (
|
136
|
+
match.output.credential_format !== "dc+sd-jwt" &&
|
137
|
+
match.output.credential_format !== "vc+sd-jwt"
|
138
|
+
) {
|
139
139
|
throw new Error("Unsupported format"); // TODO [SIW-2082]: support MDOC credentials
|
140
140
|
}
|
141
141
|
const { vct, claims } = match.output;
|
@@ -147,12 +147,12 @@ export const evaluateDcqlQuery: EvaluateDcqlQuery = (
|
|
147
147
|
required: Boolean(credentialSet.required),
|
148
148
|
}));
|
149
149
|
|
150
|
-
const [
|
150
|
+
const [cryptoContext, credential] = credentialsSdJwtByVct[vct]!;
|
151
151
|
const requiredDisclosures = Object.values(claims) as Disclosure[];
|
152
152
|
return {
|
153
153
|
id,
|
154
154
|
vct,
|
155
|
-
|
155
|
+
cryptoContext,
|
156
156
|
credential,
|
157
157
|
requiredDisclosures,
|
158
158
|
// When it is a match but no credential_sets are found, the credential is required by default
|
@@ -185,14 +185,13 @@ export const prepareRemotePresentations: PrepareRemotePresentations = async (
|
|
185
185
|
const { vp_token } = await prepareVpToken(nonce, clientId, [
|
186
186
|
item.credential,
|
187
187
|
item.requestedClaims,
|
188
|
-
|
188
|
+
item.cryptoContext,
|
189
189
|
]);
|
190
190
|
|
191
191
|
return {
|
192
192
|
credentialId: item.id,
|
193
193
|
requestedClaims: item.requestedClaims,
|
194
194
|
vpToken: vp_token,
|
195
|
-
format: "dc+sd-jwt",
|
196
195
|
};
|
197
196
|
})
|
198
197
|
);
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import { InputDescriptor, type LegacyRemotePresentation } from "./types";
|
2
2
|
import { SdJwt4VC, type DisclosureWithEncoded } from "../../sd-jwt/types";
|
3
3
|
import { decode, prepareVpToken } from "../../sd-jwt";
|
4
|
-
import { createCryptoContextFor } from "../../utils/crypto";
|
5
4
|
import { JSONPath } from "jsonpath-plus";
|
6
5
|
import { CredentialsNotFoundError, MissingDataError } from "./errors";
|
7
6
|
import Ajv from "ajv";
|
7
|
+
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
8
8
|
|
9
9
|
const ajv = new Ajv({ allErrors: true });
|
10
10
|
const INDEX_CLAIM_NAME = 1;
|
@@ -23,13 +23,16 @@ export type EvaluateInputDescriptorSdJwt4VC = (
|
|
23
23
|
|
24
24
|
export type EvaluateInputDescriptors = (
|
25
25
|
descriptors: InputDescriptor[],
|
26
|
-
credentialsSdJwt: [
|
26
|
+
credentialsSdJwt: [
|
27
|
+
CryptoContext /* cryptoContext */,
|
28
|
+
string /* credential */,
|
29
|
+
][]
|
27
30
|
) => Promise<
|
28
31
|
{
|
29
32
|
evaluatedDisclosure: EvaluatedDisclosures;
|
30
33
|
inputDescriptor: InputDescriptor;
|
31
34
|
credential: string;
|
32
|
-
|
35
|
+
cryptoContext: CryptoContext;
|
33
36
|
}[]
|
34
37
|
>;
|
35
38
|
|
@@ -41,7 +44,7 @@ export type PrepareLegacyRemotePresentations = (
|
|
41
44
|
requestedClaims: string[];
|
42
45
|
inputDescriptor: InputDescriptor;
|
43
46
|
credential: string;
|
44
|
-
|
47
|
+
cryptoContext: CryptoContext;
|
45
48
|
}[],
|
46
49
|
nonce: string,
|
47
50
|
client_id: string
|
@@ -247,7 +250,7 @@ export const evaluateInputDescriptorForSdJwt4VC: EvaluateInputDescriptorSdJwt4VC
|
|
247
250
|
};
|
248
251
|
|
249
252
|
type DecodedCredentialSdJwt = {
|
250
|
-
|
253
|
+
cryptoContext: CryptoContext;
|
251
254
|
credential: string;
|
252
255
|
sdJwt: SdJwt4VC;
|
253
256
|
disclosures: DisclosureWithEncoded[];
|
@@ -264,11 +267,11 @@ export const findCredentialSdJwt = (
|
|
264
267
|
decodedSdJwtCredentials: DecodedCredentialSdJwt[]
|
265
268
|
): {
|
266
269
|
matchedEvaluation: EvaluatedDisclosures;
|
267
|
-
matchedKeyTag: string;
|
268
270
|
matchedCredential: string;
|
271
|
+
cryptoContext: CryptoContext;
|
269
272
|
} => {
|
270
273
|
for (const {
|
271
|
-
|
274
|
+
cryptoContext,
|
272
275
|
credential,
|
273
276
|
sdJwt,
|
274
277
|
disclosures,
|
@@ -282,7 +285,7 @@ export const findCredentialSdJwt = (
|
|
282
285
|
|
283
286
|
return {
|
284
287
|
matchedEvaluation: evaluatedDisclosure,
|
285
|
-
|
288
|
+
cryptoContext,
|
286
289
|
matchedCredential: credential,
|
287
290
|
};
|
288
291
|
} catch {
|
@@ -319,9 +322,9 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
|
|
319
322
|
) => {
|
320
323
|
// We need decode SD-JWT credentials for evaluation
|
321
324
|
const decodedSdJwtCredentials =
|
322
|
-
credentialsSdJwt?.map(([
|
325
|
+
credentialsSdJwt?.map(([cryptoContext, credential]) => {
|
323
326
|
const { sdJwt, disclosures } = decode(credential);
|
324
|
-
return {
|
327
|
+
return { cryptoContext, credential, sdJwt, disclosures };
|
325
328
|
}) || [];
|
326
329
|
|
327
330
|
return Promise.all(
|
@@ -336,14 +339,14 @@ export const evaluateInputDescriptors: EvaluateInputDescriptors = async (
|
|
336
339
|
]);
|
337
340
|
}
|
338
341
|
|
339
|
-
const { matchedEvaluation,
|
342
|
+
const { matchedEvaluation, cryptoContext, matchedCredential } =
|
340
343
|
findCredentialSdJwt(descriptor, decodedSdJwtCredentials);
|
341
344
|
|
342
345
|
return {
|
343
346
|
evaluatedDisclosure: matchedEvaluation,
|
344
347
|
inputDescriptor: descriptor,
|
345
348
|
credential: matchedCredential,
|
346
|
-
|
349
|
+
cryptoContext,
|
347
350
|
};
|
348
351
|
}
|
349
352
|
|
@@ -383,7 +386,7 @@ export const prepareLegacyRemotePresentations: PrepareLegacyRemotePresentations
|
|
383
386
|
const { vp_token } = await prepareVpToken(nonce, client_id, [
|
384
387
|
item.credential,
|
385
388
|
item.requestedClaims,
|
386
|
-
|
389
|
+
item.cryptoContext,
|
387
390
|
]);
|
388
391
|
|
389
392
|
return {
|
@@ -30,7 +30,6 @@ export type LegacyRemotePresentation = {
|
|
30
30
|
export type RemotePresentation = {
|
31
31
|
requestedClaims: string[];
|
32
32
|
credentialId: string;
|
33
|
-
format: string;
|
34
33
|
vpToken: string;
|
35
34
|
};
|
36
35
|
|
@@ -97,7 +96,7 @@ export const RequestObject = z.object({
|
|
97
96
|
state: z.string().optional(),
|
98
97
|
nonce: z.string(),
|
99
98
|
response_uri: z.string(),
|
100
|
-
|
99
|
+
request_uri_method: z.string().optional(),
|
101
100
|
response_type: z.literal("vp_token"),
|
102
101
|
response_mode: z.literal("direct_post.jwt"),
|
103
102
|
client_id: z.string(),
|
package/src/sd-jwt/index.ts
CHANGED
@@ -110,7 +110,11 @@ export const disclose = async (
|
|
110
110
|
})
|
111
111
|
);
|
112
112
|
|
113
|
-
|
113
|
+
// The disclosures in the new SD-JWT aligned with version 1.0
|
114
|
+
// include a trailing "~" character.
|
115
|
+
// To avoid parsing errors, it is necessary to filter the array
|
116
|
+
// to remove any empty strings
|
117
|
+
const filteredDisclosures = rawDisclosures.filter(Boolean).filter((d) => {
|
114
118
|
const {
|
115
119
|
decoded: [, name],
|
116
120
|
} = decodeDisclosure(d);
|
package/src/sd-jwt/types.ts
CHANGED
@@ -33,12 +33,23 @@ export type DisclosureWithEncoded = {
|
|
33
33
|
encoded: string;
|
34
34
|
};
|
35
35
|
|
36
|
+
const StatusAssertion = z.object({
|
37
|
+
credential_hash_alg: z.literal("sha-256"),
|
38
|
+
});
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Type for a Verifiable Credential in SD-JWT format.
|
42
|
+
* It supports both the older and the new data model for backward compatibility.
|
43
|
+
*/
|
36
44
|
export type SdJwt4VC = z.infer<typeof SdJwt4VC>;
|
37
45
|
export const SdJwt4VC = z.object({
|
38
46
|
header: z.object({
|
39
|
-
typ: z.
|
47
|
+
typ: z.enum(["vc+sd-jwt", "dc+sd-jwt"]),
|
40
48
|
alg: z.string(),
|
41
|
-
kid: z.string()
|
49
|
+
kid: z.string(),
|
50
|
+
trust_chain: z.array(z.string()).optional(),
|
51
|
+
x5c: z.array(z.string()).optional(),
|
52
|
+
vctm: z.array(z.string()).optional(),
|
42
53
|
}),
|
43
54
|
payload: z.intersection(
|
44
55
|
z.object({
|
@@ -47,18 +58,21 @@ export const SdJwt4VC = z.object({
|
|
47
58
|
iat: UnixTime.optional(),
|
48
59
|
exp: UnixTime,
|
49
60
|
_sd_alg: z.literal("sha-256"),
|
50
|
-
status: z
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
status: z
|
62
|
+
.union([
|
63
|
+
// Credentials v1.0
|
64
|
+
z.object({ status_assertion: StatusAssertion }),
|
65
|
+
// Credentials v0.7.1
|
66
|
+
z.object({ status_attestation: StatusAssertion }),
|
67
|
+
])
|
68
|
+
.optional(),
|
55
69
|
cnf: z.object({
|
56
70
|
jwk: JWK,
|
57
71
|
}),
|
58
72
|
vct: z.string(),
|
59
|
-
"vct#integrity": z.string(),
|
60
|
-
issuing_authority: z.string(),
|
61
|
-
issuing_country: z.string(),
|
73
|
+
"vct#integrity": z.string().optional(),
|
74
|
+
issuing_authority: z.string().optional(),
|
75
|
+
issuing_country: z.string().optional(),
|
62
76
|
}),
|
63
77
|
ObfuscatedDisclosures
|
64
78
|
),
|
@@ -58,7 +58,7 @@ export const WalletInstanceAttestationJwt = z.object({
|
|
58
58
|
Jwt.shape.header,
|
59
59
|
z.object({
|
60
60
|
typ: z.literal("oauth-client-attestation+jwt"),
|
61
|
-
trust_chain: z.array(z.string()).optional(),
|
61
|
+
trust_chain: z.array(z.string()).optional(),
|
62
62
|
})
|
63
63
|
),
|
64
64
|
payload: z.intersection(
|