@pagopa/io-react-native-wallet 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
});
|