@pagopa/io-react-native-wallet 1.2.3 → 1.2.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/presentation/01-start-flow.js +12 -28
- package/lib/commonjs/credential/presentation/01-start-flow.js.map +1 -1
- package/lib/commonjs/credential/presentation/04-retrieve-rp-jwks.js +96 -24
- package/lib/commonjs/credential/presentation/04-retrieve-rp-jwks.js.map +1 -1
- package/lib/commonjs/credential/presentation/05-verify-request-object.js +7 -2
- package/lib/commonjs/credential/presentation/05-verify-request-object.js.map +1 -1
- package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +9 -5
- package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
- package/lib/commonjs/credential/presentation/README.md +4 -4
- package/lib/commonjs/credential/presentation/errors.js +2 -19
- package/lib/commonjs/credential/presentation/errors.js.map +1 -1
- package/lib/commonjs/credential/presentation/types.js +7 -1
- package/lib/commonjs/credential/presentation/types.js.map +1 -1
- package/lib/commonjs/utils/crypto.js +41 -1
- package/lib/commonjs/utils/crypto.js.map +1 -1
- package/lib/module/credential/presentation/01-start-flow.js +12 -28
- package/lib/module/credential/presentation/01-start-flow.js.map +1 -1
- package/lib/module/credential/presentation/04-retrieve-rp-jwks.js +96 -24
- package/lib/module/credential/presentation/04-retrieve-rp-jwks.js.map +1 -1
- package/lib/module/credential/presentation/05-verify-request-object.js +7 -2
- package/lib/module/credential/presentation/05-verify-request-object.js.map +1 -1
- package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +9 -5
- package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
- package/lib/module/credential/presentation/README.md +4 -4
- package/lib/module/credential/presentation/errors.js +0 -16
- package/lib/module/credential/presentation/errors.js.map +1 -1
- package/lib/module/credential/presentation/types.js +7 -1
- package/lib/module/credential/presentation/types.js.map +1 -1
- package/lib/module/utils/crypto.js +38 -0
- package/lib/module/utils/crypto.js.map +1 -1
- package/lib/typescript/credential/presentation/01-start-flow.d.ts +3 -3
- package/lib/typescript/credential/presentation/01-start-flow.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/03-get-request-object.d.ts +1 -1
- package/lib/typescript/credential/presentation/04-retrieve-rp-jwks.d.ts +15 -8
- package/lib/typescript/credential/presentation/04-retrieve-rp-jwks.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/05-verify-request-object.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts +3 -2
- package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/errors.d.ts +0 -11
- package/lib/typescript/credential/presentation/errors.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/types.d.ts +242 -3
- package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
- package/lib/typescript/utils/crypto.d.ts +24 -0
- package/lib/typescript/utils/crypto.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/credential/presentation/01-start-flow.ts +16 -32
- package/src/credential/presentation/03-get-request-object.ts +1 -1
- package/src/credential/presentation/04-retrieve-rp-jwks.ts +122 -34
- package/src/credential/presentation/05-verify-request-object.ts +4 -3
- package/src/credential/presentation/07-evaluate-input-descriptor.ts +20 -6
- package/src/credential/presentation/README.md +4 -4
- package/src/credential/presentation/errors.ts +0 -16
- package/src/credential/presentation/types.ts +8 -1
- package/src/utils/crypto.ts +43 -0
@@ -15,9 +15,10 @@ export const verifyRequestObjectSignature: VerifyRequestObjectSignature =
|
|
15
15
|
const requestObjectJwt = decodeJwt(requestObjectEncodedJwt);
|
16
16
|
|
17
17
|
// verify token signature to ensure the request object is authentic
|
18
|
-
const pubKey =
|
19
|
-
(
|
20
|
-
|
18
|
+
const pubKey =
|
19
|
+
jwkKeys?.find(
|
20
|
+
({ kid }) => kid === requestObjectJwt.protectedHeader.kid
|
21
|
+
) || jwkKeys?.find(({ use }) => use === "sig");
|
21
22
|
|
22
23
|
if (!pubKey) {
|
23
24
|
throw new UnverifiedEntityError("Request Object signature verification!");
|
@@ -9,6 +9,7 @@ const INDEX_CLAIM_NAME = 1;
|
|
9
9
|
export type EvaluatedDisclosures = {
|
10
10
|
requiredDisclosures: DisclosureWithEncoded[];
|
11
11
|
optionalDisclosures: DisclosureWithEncoded[];
|
12
|
+
unrequestedDisclosures: DisclosureWithEncoded[];
|
12
13
|
};
|
13
14
|
|
14
15
|
export type EvaluateInputDescriptorSdJwt4VC = (
|
@@ -99,8 +100,8 @@ const extractClaimName = (path: string): string | undefined => {
|
|
99
100
|
* - Validates whether required fields are present (unless marked optional)
|
100
101
|
* and match any specified JSONPath.
|
101
102
|
* - If a field includes a JSON Schema filter, validates the claim value against that schema.
|
102
|
-
* - Enforces `limit_disclosure` rules by returning only disclosures matching the specified fields
|
103
|
-
* if set to "required". Otherwise return the array
|
103
|
+
* - Enforces `limit_disclosure` rules by returning only disclosures, required and optional, matching the specified fields
|
104
|
+
* if set to "required". Otherwise also return the array unrequestedDisclosures with disclosures which can be passed for a particular use case.
|
104
105
|
* - Throws an error if a required field is invalid or missing.
|
105
106
|
*
|
106
107
|
* @param inputDescriptor - Describes constraints (fields, filters, etc.) that must be satisfied.
|
@@ -115,7 +116,8 @@ export const evaluateInputDescriptorForSdJwt4VC: EvaluateInputDescriptorSdJwt4VC
|
|
115
116
|
// No validation, all field are optional
|
116
117
|
return {
|
117
118
|
requiredDisclosures: [],
|
118
|
-
optionalDisclosures:
|
119
|
+
optionalDisclosures: [],
|
120
|
+
unrequestedDisclosures: disclosures,
|
119
121
|
};
|
120
122
|
}
|
121
123
|
const requiredClaimNames: string[] = [];
|
@@ -182,9 +184,6 @@ export const evaluateInputDescriptorForSdJwt4VC: EvaluateInputDescriptorSdJwt4VC
|
|
182
184
|
}
|
183
185
|
|
184
186
|
// Categorizes disclosures into required and optional based on claim names and disclosure constraints.
|
185
|
-
const isNotLimitDisclosure = !(
|
186
|
-
inputDescriptor.constraints.limit_disclosure === "required"
|
187
|
-
);
|
188
187
|
|
189
188
|
const requiredDisclosures = disclosures.filter((disclosure) =>
|
190
189
|
requiredClaimNames.includes(disclosure.decoded[INDEX_CLAIM_NAME])
|
@@ -197,8 +196,23 @@ export const evaluateInputDescriptorForSdJwt4VC: EvaluateInputDescriptorSdJwt4VC
|
|
197
196
|
!requiredClaimNames.includes(disclosure.decoded[INDEX_CLAIM_NAME]))
|
198
197
|
);
|
199
198
|
|
199
|
+
const isNotLimitDisclosure = !(
|
200
|
+
inputDescriptor.constraints.limit_disclosure === "required"
|
201
|
+
);
|
202
|
+
|
203
|
+
const unrequestedDisclosures = isNotLimitDisclosure
|
204
|
+
? disclosures.filter(
|
205
|
+
(disclosure) =>
|
206
|
+
!optionalClaimNames.includes(
|
207
|
+
disclosure.decoded[INDEX_CLAIM_NAME]
|
208
|
+
) &&
|
209
|
+
!requiredClaimNames.includes(disclosure.decoded[INDEX_CLAIM_NAME])
|
210
|
+
)
|
211
|
+
: [];
|
212
|
+
|
200
213
|
return {
|
201
214
|
requiredDisclosures,
|
202
215
|
optionalDisclosures,
|
216
|
+
unrequestedDisclosures,
|
203
217
|
};
|
204
218
|
};
|
@@ -29,8 +29,8 @@ sequenceDiagram
|
|
29
29
|
<summary>Remote Presentation flow</summary>
|
30
30
|
|
31
31
|
```ts
|
32
|
-
// Scan e retrive qr-code
|
33
|
-
const
|
32
|
+
// Scan e retrive qr-code, decode it and get its parameters
|
33
|
+
const {requestUri, clientId} = ...
|
34
34
|
|
35
35
|
// Retrieve the integrity key tag from the store and create its context
|
36
36
|
const integrityKeyTag = "example"; // Let's assume this is the key tag used to create the wallet instance
|
@@ -55,7 +55,7 @@ const walletInstanceAttestation =
|
|
55
55
|
});
|
56
56
|
|
57
57
|
// Start the issuance flow
|
58
|
-
const { requestURI, clientId } = Credential.Presentation.startFlowFromQR(
|
58
|
+
const { requestURI, clientId } = Credential.Presentation.startFlowFromQR(requestUri, clientId);
|
59
59
|
|
60
60
|
// If use trust federation: Evaluate issuer trust
|
61
61
|
const { rpConf } = await Credential.Presentation.evaluateRelyingPartyTrust(clientId);
|
@@ -111,4 +111,4 @@ const { presentationDefinition } = await Credential.Presentation.fetchPresentDef
|
|
111
111
|
|
112
112
|
```
|
113
113
|
|
114
|
-
</details>
|
114
|
+
</details>
|
@@ -40,22 +40,6 @@ export class NoSuitableKeysFoundInEntityConfiguration extends IoWalletError {
|
|
40
40
|
}
|
41
41
|
}
|
42
42
|
|
43
|
-
/**
|
44
|
-
* When a QR code is not valid.
|
45
|
-
*
|
46
|
-
*/
|
47
|
-
export class InvalidQRCodeError extends IoWalletError {
|
48
|
-
code = "ERR_INVALID_QR_CODE";
|
49
|
-
|
50
|
-
/**
|
51
|
-
* @param detail A description of why the QR code is considered invalid.
|
52
|
-
*/
|
53
|
-
constructor(detail: string) {
|
54
|
-
const message = `QR code is not valid: ${detail}.`;
|
55
|
-
super(message);
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
43
|
/**
|
60
44
|
* When the entity is unverified because the Relying Party is not trusted.
|
61
45
|
*
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
2
2
|
import { UnixTime } from "../../sd-jwt/types";
|
3
3
|
import * as z from "zod";
|
4
|
+
import { JWKS } from "../../utils/jwk";
|
4
5
|
|
5
6
|
/**
|
6
7
|
* A pair that associate a tokenized Verified Credential with the claims presented or requested to present.
|
@@ -77,7 +78,13 @@ export const RequestObject = z.object({
|
|
77
78
|
response_type: z.literal("vp_token"),
|
78
79
|
response_mode: z.enum(["direct_post.jwt", "direct_post"]),
|
79
80
|
client_id: z.string(),
|
80
|
-
client_id_scheme: z.string(), // previous z.literal("entity_id"),
|
81
|
+
client_id_scheme: z.string().optional(), // previous z.literal("entity_id"),
|
82
|
+
client_metadata: z
|
83
|
+
.object({
|
84
|
+
jwks_uri: z.string().optional(),
|
85
|
+
jwks: JWKS.optional(),
|
86
|
+
})
|
87
|
+
.optional(), // previous z.literal("entity_id"),
|
81
88
|
scope: z.string().optional(),
|
82
89
|
presentation_definition: PresentationDefinition.optional(),
|
83
90
|
});
|
package/src/utils/crypto.ts
CHANGED
@@ -7,6 +7,8 @@ import {
|
|
7
7
|
import uuid from "react-native-uuid";
|
8
8
|
import { thumbprint, type CryptoContext } from "@pagopa/io-react-native-jwt";
|
9
9
|
import { fixBase64EncodingOnKey } from "./jwk";
|
10
|
+
import { X509, KEYUTIL, RSAKey, KJUR } from "jsrsasign";
|
11
|
+
import { JWK } from "./jwk";
|
10
12
|
|
11
13
|
/**
|
12
14
|
* Create a CryptoContext bound to a key pair.
|
@@ -63,3 +65,44 @@ export const withEphemeralKey = async <R>(
|
|
63
65
|
const ephemeralContext = createCryptoContextFor(keytag);
|
64
66
|
return fn(ephemeralContext).finally(() => deleteKey(keytag));
|
65
67
|
};
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Converts a certificate string to PEM format.
|
71
|
+
*
|
72
|
+
* @param certificate - The certificate string.
|
73
|
+
* @returns The PEM-formatted certificate.
|
74
|
+
*/
|
75
|
+
export const convertCertToPem = (certificate: string): string =>
|
76
|
+
`-----BEGIN CERTIFICATE-----\n${certificate}\n-----END CERTIFICATE-----`;
|
77
|
+
|
78
|
+
/**
|
79
|
+
* Parses the public key from a PEM-formatted certificate.
|
80
|
+
*
|
81
|
+
* @param pemCert - The PEM-formatted certificate.
|
82
|
+
* @returns The public key object.
|
83
|
+
* @throws Will throw an error if the public key is unsupported.
|
84
|
+
*/
|
85
|
+
export const parsePublicKey = (
|
86
|
+
pemCert: string
|
87
|
+
): RSAKey | KJUR.crypto.ECDSA | undefined => {
|
88
|
+
const x509 = new X509();
|
89
|
+
x509.readCertPEM(pemCert);
|
90
|
+
const publicKey = x509.getPublicKey();
|
91
|
+
|
92
|
+
if (publicKey instanceof RSAKey || publicKey instanceof KJUR.crypto.ECDSA) {
|
93
|
+
return publicKey;
|
94
|
+
}
|
95
|
+
|
96
|
+
return undefined;
|
97
|
+
};
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Retrieves the signing JWK from the public key.
|
101
|
+
*
|
102
|
+
* @param publicKey - The public key object.
|
103
|
+
* @returns The signing JWK.
|
104
|
+
*/
|
105
|
+
export const getSigningJwk = (publicKey: RSAKey | KJUR.crypto.ECDSA): JWK => ({
|
106
|
+
...JWK.parse(KEYUTIL.getJWKFromKey(publicKey)),
|
107
|
+
use: "sig",
|
108
|
+
});
|