@pagopa/io-react-native-wallet 0.1.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.
- package/README.md +91 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/pid/index.js +11 -0
- package/lib/commonjs/pid/index.js.map +1 -0
- package/lib/commonjs/pid/sd-jwt/converters.js +29 -0
- package/lib/commonjs/pid/sd-jwt/converters.js.map +1 -0
- package/lib/commonjs/pid/sd-jwt/index.js +76 -0
- package/lib/commonjs/pid/sd-jwt/index.js.map +1 -0
- package/lib/commonjs/pid/sd-jwt/types.js +50 -0
- package/lib/commonjs/pid/sd-jwt/types.js.map +1 -0
- package/lib/commonjs/sd-jwt/__test__/converters.test.js +25 -0
- package/lib/commonjs/sd-jwt/__test__/converters.test.js.map +1 -0
- package/lib/commonjs/sd-jwt/__test__/types.test.js +70 -0
- package/lib/commonjs/sd-jwt/__test__/types.test.js.map +1 -0
- package/lib/commonjs/sd-jwt/converters.js +30 -0
- package/lib/commonjs/sd-jwt/converters.js.map +1 -0
- package/lib/commonjs/sd-jwt/index.js +77 -0
- package/lib/commonjs/sd-jwt/index.js.map +1 -0
- package/lib/commonjs/sd-jwt/types.js +53 -0
- package/lib/commonjs/sd-jwt/types.js.map +1 -0
- package/lib/commonjs/sd-jwt/verifier.js +18 -0
- package/lib/commonjs/sd-jwt/verifier.js.map +1 -0
- package/lib/commonjs/utils/errors.js +82 -0
- package/lib/commonjs/utils/errors.js.map +1 -0
- package/lib/commonjs/utils/jwk.js +45 -0
- package/lib/commonjs/utils/jwk.js.map +1 -0
- package/lib/commonjs/wallet-instance-attestation/index.js +63 -0
- package/lib/commonjs/wallet-instance-attestation/index.js.map +1 -0
- package/lib/commonjs/wallet-instance-attestation/issuing.js +96 -0
- package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -0
- package/lib/commonjs/wallet-instance-attestation/types.js +65 -0
- package/lib/commonjs/wallet-instance-attestation/types.js.map +1 -0
- package/lib/module/index.js +7 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/pid/index.js +3 -0
- package/lib/module/pid/index.js.map +1 -0
- package/lib/module/pid/sd-jwt/converters.js +23 -0
- package/lib/module/pid/sd-jwt/converters.js.map +1 -0
- package/lib/module/pid/sd-jwt/index.js +66 -0
- package/lib/module/pid/sd-jwt/index.js.map +1 -0
- package/lib/module/pid/sd-jwt/types.js +43 -0
- package/lib/module/pid/sd-jwt/types.js.map +1 -0
- package/lib/module/sd-jwt/__test__/converters.test.js +23 -0
- package/lib/module/sd-jwt/__test__/converters.test.js.map +1 -0
- package/lib/module/sd-jwt/__test__/types.test.js +68 -0
- package/lib/module/sd-jwt/__test__/types.test.js.map +1 -0
- package/lib/module/sd-jwt/converters.js +24 -0
- package/lib/module/sd-jwt/converters.js.map +1 -0
- package/lib/module/sd-jwt/index.js +71 -0
- package/lib/module/sd-jwt/index.js.map +1 -0
- package/lib/module/sd-jwt/types.js +44 -0
- package/lib/module/sd-jwt/types.js.map +1 -0
- package/lib/module/sd-jwt/verifier.js +11 -0
- package/lib/module/sd-jwt/verifier.js.map +1 -0
- package/lib/module/utils/errors.js +73 -0
- package/lib/module/utils/errors.js.map +1 -0
- package/lib/module/utils/jwk.js +38 -0
- package/lib/module/utils/jwk.js.map +1 -0
- package/lib/module/wallet-instance-attestation/index.js +52 -0
- package/lib/module/wallet-instance-attestation/index.js.map +1 -0
- package/lib/module/wallet-instance-attestation/issuing.js +90 -0
- package/lib/module/wallet-instance-attestation/issuing.js.map +1 -0
- package/lib/module/wallet-instance-attestation/types.js +55 -0
- package/lib/module/wallet-instance-attestation/types.js.map +1 -0
- package/lib/typescript/index.d.ts +5 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/pid/index.d.ts +3 -0
- package/lib/typescript/pid/index.d.ts.map +1 -0
- package/lib/typescript/pid/sd-jwt/converters.d.ts +4 -0
- package/lib/typescript/pid/sd-jwt/converters.d.ts.map +1 -0
- package/lib/typescript/pid/sd-jwt/index.d.ts +50 -0
- package/lib/typescript/pid/sd-jwt/index.d.ts.map +1 -0
- package/lib/typescript/pid/sd-jwt/types.d.ts +196 -0
- package/lib/typescript/pid/sd-jwt/types.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/__test__/converters.test.d.ts +2 -0
- package/lib/typescript/sd-jwt/__test__/converters.test.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/__test__/types.test.d.ts +2 -0
- package/lib/typescript/sd-jwt/__test__/types.test.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/converters.d.ts +3 -0
- package/lib/typescript/sd-jwt/converters.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/index.d.ts +42 -0
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/types.d.ts +416 -0
- package/lib/typescript/sd-jwt/types.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/verifier.d.ts +3 -0
- package/lib/typescript/sd-jwt/verifier.d.ts.map +1 -0
- package/lib/typescript/utils/errors.d.ts +45 -0
- package/lib/typescript/utils/errors.d.ts.map +1 -0
- package/lib/typescript/utils/jwk.d.ts +85 -0
- package/lib/typescript/utils/jwk.d.ts.map +1 -0
- package/lib/typescript/wallet-instance-attestation/index.d.ts +36 -0
- package/lib/typescript/wallet-instance-attestation/index.d.ts.map +1 -0
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts +32 -0
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -0
- package/lib/typescript/wallet-instance-attestation/types.d.ts +733 -0
- package/lib/typescript/wallet-instance-attestation/types.d.ts.map +1 -0
- package/package.json +108 -0
- package/src/index.ts +8 -0
- package/src/pid/index.ts +2 -0
- package/src/pid/sd-jwt/converters.ts +26 -0
- package/src/pid/sd-jwt/index.ts +71 -0
- package/src/pid/sd-jwt/types.ts +44 -0
- package/src/sd-jwt/__test__/converters.test.ts +27 -0
- package/src/sd-jwt/__test__/types.test.ts +85 -0
- package/src/sd-jwt/converters.ts +24 -0
- package/src/sd-jwt/index.ts +92 -0
- package/src/sd-jwt/types.ts +54 -0
- package/src/sd-jwt/verifier.ts +20 -0
- package/src/utils/errors.ts +74 -0
- package/src/utils/jwk.ts +39 -0
- package/src/wallet-instance-attestation/index.ts +56 -0
- package/src/wallet-instance-attestation/issuing.ts +107 -0
- package/src/wallet-instance-attestation/types.ts +77 -0
package/src/utils/jwk.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export type JWK = z.infer<typeof JWK>;
|
|
4
|
+
export const JWK = z.object({
|
|
5
|
+
/** JWK "alg" (Algorithm) Parameter. */
|
|
6
|
+
alg: z.string().optional(),
|
|
7
|
+
crv: z.string().optional(),
|
|
8
|
+
d: z.string().optional(),
|
|
9
|
+
dp: z.string().optional(),
|
|
10
|
+
dq: z.string().optional(),
|
|
11
|
+
e: z.string().optional(),
|
|
12
|
+
/** JWK "ext" (Extractable) Parameter. */
|
|
13
|
+
ext: z.boolean().optional(),
|
|
14
|
+
k: z.string().optional(),
|
|
15
|
+
/** JWK "key_ops" (Key Operations) Parameter. */
|
|
16
|
+
key_ops: z.array(z.string()).optional(),
|
|
17
|
+
/** JWK "kid" (Key ID) Parameter. */
|
|
18
|
+
kid: z.string().optional(),
|
|
19
|
+
/** JWK "kty" (Key Type) Parameter.
|
|
20
|
+
* This attribute is required to discriminate the
|
|
21
|
+
* type of EC/RSA algorithm */
|
|
22
|
+
kty: z.union([z.literal("RSA"), z.literal("EC")]),
|
|
23
|
+
n: z.string().optional(),
|
|
24
|
+
p: z.string().optional(),
|
|
25
|
+
q: z.string().optional(),
|
|
26
|
+
qi: z.string().optional(),
|
|
27
|
+
/** JWK "use" (Public Key Use) Parameter. */
|
|
28
|
+
use: z.string().optional(),
|
|
29
|
+
x: z.string().optional(),
|
|
30
|
+
y: z.string().optional(),
|
|
31
|
+
/** JWK "x5c" (X.509 Certificate Chain) Parameter. */
|
|
32
|
+
x5c: z.array(z.string()).optional(),
|
|
33
|
+
/** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter. */
|
|
34
|
+
x5t: z.string().optional(),
|
|
35
|
+
/** "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter. */
|
|
36
|
+
"x5t#S256": z.string().optional(),
|
|
37
|
+
/** JWK "x5u" (X.509 URL) Parameter. */
|
|
38
|
+
x5u: z.string().optional(),
|
|
39
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { WalletInstanceAttestationJwt } from "./types";
|
|
2
|
+
import { decode as decodeJwt } from "@pagopa/io-react-native-jwt";
|
|
3
|
+
import { verify as verifyJwt } from "@pagopa/io-react-native-jwt";
|
|
4
|
+
|
|
5
|
+
import { Issuing } from "./issuing";
|
|
6
|
+
export { Issuing };
|
|
7
|
+
/**
|
|
8
|
+
* Decode a given JWT to get the parsed Wallet Instance Attestation object they define.
|
|
9
|
+
* It ensures provided data is in a valid shape.
|
|
10
|
+
*
|
|
11
|
+
* It DOES NOT verify token signature nor check disclosures are correctly referenced by the JWT.
|
|
12
|
+
* Use {@link verify} instead
|
|
13
|
+
*
|
|
14
|
+
* @function
|
|
15
|
+
* @param token The encoded token that represents a valid jwt for Wallet Instance Attestation
|
|
16
|
+
*
|
|
17
|
+
* @returns The validated Wallet Instance Attestation object
|
|
18
|
+
* @throws A decoding error if the token doesn't resolve in a valid JWT
|
|
19
|
+
* @throws A validation error if the provided data doesn't result in a valid Wallet Instance Attestation
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
export function decode(token: string): WalletInstanceAttestationJwt {
|
|
23
|
+
// decode JWT parts
|
|
24
|
+
const decodedJwt = decodeJwt(token);
|
|
25
|
+
// parse JWT to ensure it has the shape of a WalletInstanceAttestationJwt
|
|
26
|
+
return WalletInstanceAttestationJwt.parse({
|
|
27
|
+
header: decodedJwt.protectedHeader,
|
|
28
|
+
payload: decodedJwt.payload,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Verify a given JWT to get the parsed Wallet Instance Attestation object they define.
|
|
34
|
+
* Same as {@link decode} plus token signature verification
|
|
35
|
+
*
|
|
36
|
+
* @async @function
|
|
37
|
+
*
|
|
38
|
+
*
|
|
39
|
+
* @param token The encoded token that represents a valid jwt
|
|
40
|
+
*
|
|
41
|
+
* @returns {WalletInstanceAttestationJwt} The validated Wallet Instance Attestation object
|
|
42
|
+
* @throws A decoding error if the token doesn't resolve in a valid JWT
|
|
43
|
+
* @throws A validation error if the provided data doesn't result in a valid Wallet Instance Attestation
|
|
44
|
+
* @throws Invalid signature error if the token signature is not valid
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
export async function verify(
|
|
48
|
+
token: string
|
|
49
|
+
): Promise<WalletInstanceAttestationJwt> {
|
|
50
|
+
const decoded = decode(token);
|
|
51
|
+
const pubKey = decoded.payload.cnf.jwk;
|
|
52
|
+
|
|
53
|
+
await verifyJwt(token, pubKey);
|
|
54
|
+
|
|
55
|
+
return decoded;
|
|
56
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { decode as decodeJwt } from "@pagopa/io-react-native-jwt";
|
|
2
|
+
import { verify as verifyJwt } from "@pagopa/io-react-native-jwt";
|
|
3
|
+
import { SignJWT, thumbprint } from "@pagopa/io-react-native-jwt";
|
|
4
|
+
import { JWK } from "../utils/jwk";
|
|
5
|
+
import { WalletInstanceAttestationRequestJwt } from "./types";
|
|
6
|
+
import uuid from "react-native-uuid";
|
|
7
|
+
import { WalletInstanceAttestationIssuingError } from "../utils/errors";
|
|
8
|
+
|
|
9
|
+
export class Issuing {
|
|
10
|
+
walletProviderBaseUrl: string;
|
|
11
|
+
|
|
12
|
+
constructor(walletProviderBaseUrl: string) {
|
|
13
|
+
this.walletProviderBaseUrl = walletProviderBaseUrl;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get the Wallet Instance Attestation Request to sign
|
|
18
|
+
*
|
|
19
|
+
* @async @function
|
|
20
|
+
*
|
|
21
|
+
* @param jwk Public key of the wallet instance
|
|
22
|
+
*
|
|
23
|
+
* @returns {string} Wallet Instance Attestation Request to sign
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
async getAttestationRequestToSign(jwk: JWK): Promise<string> {
|
|
27
|
+
const parsedJwk = JWK.parse(jwk);
|
|
28
|
+
const keyThumbprint = await thumbprint(parsedJwk);
|
|
29
|
+
const publicKey = { ...parsedJwk, kid: keyThumbprint };
|
|
30
|
+
|
|
31
|
+
const walletInstanceAttestationRequest = new SignJWT({
|
|
32
|
+
iss: keyThumbprint,
|
|
33
|
+
sub: this.walletProviderBaseUrl,
|
|
34
|
+
jti: `${uuid.v4()}`,
|
|
35
|
+
type: "WalletInstanceAttestationRequest",
|
|
36
|
+
cnf: {
|
|
37
|
+
jwk: publicKey,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
.setProtectedHeader({
|
|
41
|
+
alg: "ES256",
|
|
42
|
+
kid: publicKey.kid,
|
|
43
|
+
typ: "var+jwt",
|
|
44
|
+
})
|
|
45
|
+
.setIssuedAt()
|
|
46
|
+
.setExpirationTime("1h")
|
|
47
|
+
.toSign();
|
|
48
|
+
|
|
49
|
+
return walletInstanceAttestationRequest;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get the Wallet Instance Attestation given a
|
|
54
|
+
* Wallet Instance Attestation Request and signature
|
|
55
|
+
*
|
|
56
|
+
* @async @function
|
|
57
|
+
*
|
|
58
|
+
* @param attestationRequest Wallet Instance Attestaion Request
|
|
59
|
+
* obtained with {@link getAttestationRequestToSign}
|
|
60
|
+
* @param signature Signature of the Wallet Instance Attestaion Request
|
|
61
|
+
* @param appFetch Optional object with fetch function to use
|
|
62
|
+
*
|
|
63
|
+
* @returns {string} Wallet Instance Attestation
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
async getAttestation(
|
|
67
|
+
attestationRequest: string,
|
|
68
|
+
signature: string,
|
|
69
|
+
appFetch: GlobalFetch = { fetch }
|
|
70
|
+
): Promise<String> {
|
|
71
|
+
const signedAttestationRequest = await SignJWT.appendSignature(
|
|
72
|
+
attestationRequest,
|
|
73
|
+
signature
|
|
74
|
+
);
|
|
75
|
+
const decodedRequest = decodeJwt(signedAttestationRequest);
|
|
76
|
+
const parsedRequest = WalletInstanceAttestationRequestJwt.parse({
|
|
77
|
+
payload: decodedRequest.payload,
|
|
78
|
+
header: decodedRequest.protectedHeader,
|
|
79
|
+
});
|
|
80
|
+
const publicKey = parsedRequest.payload.cnf.jwk;
|
|
81
|
+
|
|
82
|
+
await verifyJwt(signedAttestationRequest, publicKey);
|
|
83
|
+
|
|
84
|
+
const tokenUrl = new URL("token", this.walletProviderBaseUrl).href;
|
|
85
|
+
const requestBody = {
|
|
86
|
+
grant_type:
|
|
87
|
+
"urn:ietf:params:oauth:client-assertion-type:jwt-key-attestation",
|
|
88
|
+
assertion: signedAttestationRequest,
|
|
89
|
+
};
|
|
90
|
+
const response = await appFetch.fetch(tokenUrl, {
|
|
91
|
+
method: "POST",
|
|
92
|
+
headers: {
|
|
93
|
+
"Content-Type": "application/json",
|
|
94
|
+
},
|
|
95
|
+
body: JSON.stringify(requestBody),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (response.status === 201) {
|
|
99
|
+
return await response.text();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
throw new WalletInstanceAttestationIssuingError(
|
|
103
|
+
"Unable to obtain wallet instance attestation from wallet provider",
|
|
104
|
+
`Response code: ${response.status}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { JWK } from "../utils/jwk";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
|
|
4
|
+
const UnixTime = z.number().min(0).max(2147483647000);
|
|
5
|
+
type UnixTime = z.infer<typeof UnixTime>;
|
|
6
|
+
|
|
7
|
+
const Jwt = z.object({
|
|
8
|
+
header: z.object({
|
|
9
|
+
alg: z.string(),
|
|
10
|
+
kid: z.string(),
|
|
11
|
+
typ: z.string(),
|
|
12
|
+
x5c: z.array(z.string()).optional(),
|
|
13
|
+
trust_chain: z.array(z.string()).optional(),
|
|
14
|
+
}),
|
|
15
|
+
payload: z.object({
|
|
16
|
+
iss: z.string(),
|
|
17
|
+
sub: z.string(),
|
|
18
|
+
iat: UnixTime,
|
|
19
|
+
exp: UnixTime,
|
|
20
|
+
cnf: z.object({
|
|
21
|
+
jwk: JWK,
|
|
22
|
+
}),
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export type WalletInstanceAttestationRequestJwt = z.infer<
|
|
27
|
+
typeof WalletInstanceAttestationRequestJwt
|
|
28
|
+
>;
|
|
29
|
+
export const WalletInstanceAttestationRequestJwt = z.object({
|
|
30
|
+
header: z.intersection(
|
|
31
|
+
Jwt.shape.header,
|
|
32
|
+
z.object({
|
|
33
|
+
typ: z.literal("var+jwt"),
|
|
34
|
+
})
|
|
35
|
+
),
|
|
36
|
+
payload: z.intersection(
|
|
37
|
+
Jwt.shape.payload,
|
|
38
|
+
z.object({
|
|
39
|
+
jti: z.string(),
|
|
40
|
+
type: z.literal("WalletInstanceAttestationRequest"),
|
|
41
|
+
})
|
|
42
|
+
),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export type WalletInstanceAttestationJwt = z.infer<
|
|
46
|
+
typeof WalletInstanceAttestationJwt
|
|
47
|
+
>;
|
|
48
|
+
export const WalletInstanceAttestationJwt = z.object({
|
|
49
|
+
header: z.intersection(
|
|
50
|
+
Jwt.shape.header,
|
|
51
|
+
z.object({
|
|
52
|
+
typ: z.literal("va+jwt"),
|
|
53
|
+
})
|
|
54
|
+
),
|
|
55
|
+
payload: z.intersection(
|
|
56
|
+
Jwt.shape.payload,
|
|
57
|
+
z.object({
|
|
58
|
+
type: z.literal("WalletInstanceAttestation"),
|
|
59
|
+
policy_uri: z.string().url(),
|
|
60
|
+
tos_uri: z.string().url(),
|
|
61
|
+
logo_uri: z.string().url(),
|
|
62
|
+
asc: z.string(),
|
|
63
|
+
authorization_endpoint: z.string().url(),
|
|
64
|
+
response_types_supported: z.array(z.string()),
|
|
65
|
+
vp_formats_supported: z.object({
|
|
66
|
+
jwt_vp_json: z.object({
|
|
67
|
+
alg_values_supported: z.array(z.string()),
|
|
68
|
+
}),
|
|
69
|
+
jwt_vc_json: z.object({
|
|
70
|
+
alg_values_supported: z.array(z.string()),
|
|
71
|
+
}),
|
|
72
|
+
}),
|
|
73
|
+
request_object_signing_alg_values_supported: z.array(z.string()),
|
|
74
|
+
presentation_definition_uri_supported: z.boolean(),
|
|
75
|
+
})
|
|
76
|
+
),
|
|
77
|
+
});
|