@pagopa/io-react-native-wallet 0.1.0 → 0.1.1

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 (59) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/index.js +19 -5
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/rp/__test__/index.test.js +18 -0
  5. package/lib/commonjs/rp/__test__/index.test.js.map +1 -0
  6. package/lib/commonjs/rp/index.js +116 -0
  7. package/lib/commonjs/rp/index.js.map +1 -0
  8. package/lib/commonjs/rp/types.js +72 -0
  9. package/lib/commonjs/rp/types.js.map +1 -0
  10. package/lib/commonjs/utils/dpop.js +27 -0
  11. package/lib/commonjs/utils/dpop.js.map +1 -0
  12. package/lib/commonjs/utils/errors.js +25 -1
  13. package/lib/commonjs/utils/errors.js.map +1 -1
  14. package/lib/commonjs/utils/signature.js +10 -0
  15. package/lib/commonjs/utils/signature.js.map +1 -0
  16. package/lib/commonjs/wallet-instance-attestation/issuing.js +3 -5
  17. package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -1
  18. package/lib/module/index.js +5 -4
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/rp/__test__/index.test.js +16 -0
  21. package/lib/module/rp/__test__/index.test.js.map +1 -0
  22. package/lib/module/rp/index.js +108 -0
  23. package/lib/module/rp/index.js.map +1 -0
  24. package/lib/module/rp/types.js +63 -0
  25. package/lib/module/rp/types.js.map +1 -0
  26. package/lib/module/utils/dpop.js +17 -0
  27. package/lib/module/utils/dpop.js.map +1 -0
  28. package/lib/module/utils/errors.js +23 -0
  29. package/lib/module/utils/errors.js.map +1 -1
  30. package/lib/module/utils/signature.js +3 -0
  31. package/lib/module/utils/signature.js.map +1 -0
  32. package/lib/module/wallet-instance-attestation/issuing.js +3 -5
  33. package/lib/module/wallet-instance-attestation/issuing.js.map +1 -1
  34. package/lib/typescript/index.d.ts +5 -2
  35. package/lib/typescript/index.d.ts.map +1 -1
  36. package/lib/typescript/rp/__test__/index.test.d.ts +2 -0
  37. package/lib/typescript/rp/__test__/index.test.d.ts.map +1 -0
  38. package/lib/typescript/rp/index.d.ts +43 -0
  39. package/lib/typescript/rp/index.d.ts.map +1 -0
  40. package/lib/typescript/rp/types.d.ts +840 -0
  41. package/lib/typescript/rp/types.d.ts.map +1 -0
  42. package/lib/typescript/utils/dpop.d.ts +21 -0
  43. package/lib/typescript/utils/dpop.d.ts.map +1 -0
  44. package/lib/typescript/utils/errors.d.ts +13 -0
  45. package/lib/typescript/utils/errors.d.ts.map +1 -1
  46. package/lib/typescript/utils/signature.d.ts +2 -0
  47. package/lib/typescript/utils/signature.d.ts.map +1 -0
  48. package/lib/typescript/wallet-instance-attestation/issuing.d.ts +3 -3
  49. package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -1
  50. package/lib/typescript/wallet-instance-attestation/types.d.ts +4 -4
  51. package/package.json +1 -1
  52. package/src/index.ts +12 -5
  53. package/src/rp/__test__/index.test.ts +23 -0
  54. package/src/rp/index.ts +150 -0
  55. package/src/rp/types.ts +64 -0
  56. package/src/utils/dpop.ts +25 -0
  57. package/src/utils/errors.ts +24 -0
  58. package/src/utils/signature.ts +4 -0
  59. package/src/wallet-instance-attestation/issuing.ts +8 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/rp/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAC1D,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoBxB,CAAC;AAGH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkChC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import * as z from "zod";
2
+ import type { JWK } from "./jwk";
3
+ export declare const getUnsignedDPop: (jwk: JWK, payload: DPoPPayload) => string;
4
+ export type DPoPPayload = z.infer<typeof DPoPPayload>;
5
+ export declare const DPoPPayload: z.ZodObject<{
6
+ jti: z.ZodString;
7
+ htm: z.ZodUnion<[z.ZodLiteral<"POST">, z.ZodLiteral<"GET">]>;
8
+ htu: z.ZodString;
9
+ ath: z.ZodString;
10
+ }, "strip", z.ZodTypeAny, {
11
+ jti: string;
12
+ htm: "GET" | "POST";
13
+ htu: string;
14
+ ath: string;
15
+ }, {
16
+ jti: string;
17
+ htm: "GET" | "POST";
18
+ htu: string;
19
+ ath: string;
20
+ }>;
21
+ //# sourceMappingURL=dpop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../../../src/utils/dpop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAGzB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,eAAO,MAAM,eAAe,QAAS,GAAG,WAAW,WAAW,KAAG,MAWhE,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AACtD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAKtB,CAAC"}
@@ -42,4 +42,17 @@ export declare class WalletInstanceAttestationIssuingError extends IoWalletError
42
42
  reason: string;
43
43
  constructor(message: string, claim?: string, reason?: string);
44
44
  }
45
+ /**
46
+ * An error subclass thrown when auth request decode fail
47
+ *
48
+ */
49
+ export declare class AuthRequestDecodeError extends IoWalletError {
50
+ static get code(): "ERR_IO_WALLET_AUTHENTICATION_REQUEST_DECODE_FAILED";
51
+ code: string;
52
+ /** The Claim for which the validation failed. */
53
+ claim: string;
54
+ /** Reason code for the validation failure. */
55
+ reason: string;
56
+ constructor(message: string, claim?: string, reason?: string);
57
+ }
45
58
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,6DAA6D;IAC7D,MAAM,KAAK,IAAI,IAAI,MAAM,CAExB;IAED,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAA2B;gBAE3B,OAAO,CAAC,EAAE,MAAM;CAM7B;AACD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,MAAM,KAAK,IAAI,IAAI,iCAAiC,CAEnD;IAED,IAAI,SAAqC;IAEzC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,MAAM,SAAgB;CAK3E;AAED;;;GAGG;AACH,qBAAa,qCAAsC,SAAQ,aAAa;IACtE,MAAM,KAAK,IAAI,IAAI,mDAAmD,CAErE;IAED,IAAI,SAAuD;IAE3D,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,MAAM,SAAgB;CAK3E"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,6DAA6D;IAC7D,MAAM,KAAK,IAAI,IAAI,MAAM,CAExB;IAED,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAA2B;gBAE3B,OAAO,CAAC,EAAE,MAAM;CAM7B;AACD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,MAAM,KAAK,IAAI,IAAI,iCAAiC,CAEnD;IAED,IAAI,SAAqC;IAEzC,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,MAAM,SAAgB;CAK3E;AAED;;;GAGG;AACH,qBAAa,qCAAsC,SAAQ,aAAa;IACtE,MAAM,KAAK,IAAI,IAAI,mDAAmD,CAErE;IAED,IAAI,SAAuD;IAE3D,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,MAAM,SAAgB;CAK3E;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,MAAM,KAAK,IAAI,IAAI,oDAAoD,CAEtE;IAED,IAAI,SAAwD;IAE5D,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,MAAM,SAAgB;CAK3E"}
@@ -0,0 +1,2 @@
1
+ export declare const getSignedJwt: (unsignedJwt: string, signature: string) => Promise<string>;
2
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../../src/utils/signature.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,gBAAuB,MAAM,aAAa,MAAM,oBAClB,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import { JWK } from "../utils/jwk";
2
2
  export declare class Issuing {
3
3
  walletProviderBaseUrl: string;
4
- constructor(walletProviderBaseUrl: string);
4
+ appFetch: GlobalFetch["fetch"];
5
+ constructor(walletProviderBaseUrl: string, appFetch?: GlobalFetch["fetch"]);
5
6
  /**
6
7
  * Get the Wallet Instance Attestation Request to sign
7
8
  *
@@ -22,11 +23,10 @@ export declare class Issuing {
22
23
  * @param attestationRequest Wallet Instance Attestaion Request
23
24
  * obtained with {@link getAttestationRequestToSign}
24
25
  * @param signature Signature of the Wallet Instance Attestaion Request
25
- * @param appFetch Optional object with fetch function to use
26
26
  *
27
27
  * @returns {string} Wallet Instance Attestation
28
28
  *
29
29
  */
30
- getAttestation(attestationRequest: string, signature: string, appFetch?: GlobalFetch): Promise<String>;
30
+ getAttestation(attestationRequest: string, signature: string): Promise<String>;
31
31
  }
32
32
  //# sourceMappingURL=issuing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"issuing.d.ts","sourceRoot":"","sources":["../../../src/wallet-instance-attestation/issuing.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAKnC,qBAAa,OAAO;IAClB,qBAAqB,EAAE,MAAM,CAAC;gBAElB,qBAAqB,EAAE,MAAM;IAIzC;;;;;;;;;OASG;IACG,2BAA2B,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B5D;;;;;;;;;;;;;OAaG;IACG,cAAc,CAClB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,WAAuB,GAChC,OAAO,CAAC,MAAM,CAAC;CAqCnB"}
1
+ {"version":3,"file":"issuing.d.ts","sourceRoot":"","sources":["../../../src/wallet-instance-attestation/issuing.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAKnC,qBAAa,OAAO;IAClB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;gBAE7B,qBAAqB,EAAE,MAAM,EAC7B,QAAQ,GAAE,WAAW,CAAC,OAAO,CAAS;IAMxC;;;;;;;;;OASG;IACG,2BAA2B,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B5D;;;;;;;;;;;;OAYG;IACG,cAAc,CAClB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC;CAqCnB"}
@@ -575,8 +575,8 @@ export declare const WalletInstanceAttestationJwt: z.ZodObject<{
575
575
  }, "strip", z.ZodTypeAny, {
576
576
  type: "WalletInstanceAttestation";
577
577
  policy_uri: string;
578
- tos_uri: string;
579
578
  logo_uri: string;
579
+ tos_uri: string;
580
580
  asc: string;
581
581
  authorization_endpoint: string;
582
582
  response_types_supported: string[];
@@ -593,8 +593,8 @@ export declare const WalletInstanceAttestationJwt: z.ZodObject<{
593
593
  }, {
594
594
  type: "WalletInstanceAttestation";
595
595
  policy_uri: string;
596
- tos_uri: string;
597
596
  logo_uri: string;
597
+ tos_uri: string;
598
598
  asc: string;
599
599
  authorization_endpoint: string;
600
600
  response_types_supported: string[];
@@ -653,8 +653,8 @@ export declare const WalletInstanceAttestationJwt: z.ZodObject<{
653
653
  } & {
654
654
  type: "WalletInstanceAttestation";
655
655
  policy_uri: string;
656
- tos_uri: string;
657
656
  logo_uri: string;
657
+ tos_uri: string;
658
658
  asc: string;
659
659
  authorization_endpoint: string;
660
660
  response_types_supported: string[];
@@ -713,8 +713,8 @@ export declare const WalletInstanceAttestationJwt: z.ZodObject<{
713
713
  } & {
714
714
  type: "WalletInstanceAttestation";
715
715
  policy_uri: string;
716
- tos_uri: string;
717
716
  logo_uri: string;
717
+ tos_uri: string;
718
718
  asc: string;
719
719
  authorization_endpoint: string;
720
720
  response_types_supported: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagopa/io-react-native-wallet",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Provide data structures, helpers and API for IO Wallet",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
package/src/index.ts CHANGED
@@ -1,8 +1,15 @@
1
1
  import * as PID from "./pid";
2
+ import * as RP from "./rp";
3
+ import * as Errors from "./utils/errors";
2
4
  import * as WalletInstanceAttestation from "./wallet-instance-attestation";
5
+ import { getUnsignedDPop } from "./utils/dpop";
6
+ import { getSignedJwt } from "./utils/signature";
3
7
 
4
- export function multiply(a: number, b: number): Promise<number> {
5
- return Promise.resolve(a * b);
6
- }
7
-
8
- export { PID, WalletInstanceAttestation };
8
+ export {
9
+ PID,
10
+ RP,
11
+ WalletInstanceAttestation,
12
+ Errors,
13
+ getUnsignedDPop,
14
+ getSignedJwt,
15
+ };
@@ -0,0 +1,23 @@
1
+ import { RelyingPartySolution } from "..";
2
+ import { AuthRequestDecodeError } from "../../utils/errors";
3
+
4
+ const walletInstanceAttestation =
5
+ "eyJhbGciOiJFUzI1NiIsImtpZCI6IjV0NVlZcEJoTi1FZ0lFRUk1aVV6cjZyME1SMDJMblZRME9tZWttTktjalkiLCJ0cnVzdF9jaGFpbiI6WyJleUpoYkdjaU9pSkZVei4uLjZTMEEiLCJleUpoYkdjaU9pSkZVei4uLmpKTEEiLCJleUpoYkdjaU9pSkZVei4uLkg5Z3ciXSwidHlwIjoidmErand0IiwieDVjIjpbIk1JSUJqRENDIC4uLiBYRmVoZ0tRQT09Il19.eyJpc3MiOiJodHRwczovL3dhbGxldC1wcm92aWRlci5leGFtcGxlLm9yZyIsInN1YiI6InZiZVhKa3NNNDV4cGh0QU5uQ2lHNm1DeXVVNGpmR056b3BHdUt2b2dnOWMiLCJ0eXBlIjoiV2FsbGV0SW5zdGFuY2VBdHRlc3RhdGlvbiIsInBvbGljeV91cmkiOiJodHRwczovL3dhbGxldC1wcm92aWRlci5leGFtcGxlLm9yZy9wcml2YWN5X3BvbGljeSIsInRvc191cmkiOiJodHRwczovL3dhbGxldC1wcm92aWRlci5leGFtcGxlLm9yZy9pbmZvX3BvbGljeSIsImxvZ29fdXJpIjoiaHR0cHM6Ly93YWxsZXQtcHJvdmlkZXIuZXhhbXBsZS5vcmcvbG9nby5zdmciLCJhc2MiOiJodHRwczovL3dhbGxldC1wcm92aWRlci5leGFtcGxlLm9yZy9Mb0EvYmFzaWMiLCJjbmYiOnsiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiNEhOcHRJLXhyMnBqeVJKS0dNbno0V21kblFEX3VKU3E0Ujk1Tmo5OGI0NCIsInkiOiJMSVpuU0IzOXZGSmhZZ1MzazdqWEU0cjMtQ29HRlF3WnRQQklScXBObHJnIiwia2lkIjoidmJlWEprc000NXhwaHRBTm5DaUc2bUN5dVU0amZHTnpvcEd1S3ZvZ2c5YyJ9fSwiYXV0aG9yaXphdGlvbl9lbmRwb2ludCI6ImV1ZGl3OiIsInJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZCI6WyJ2cF90b2tlbiJdLCJ2cF9mb3JtYXRzX3N1cHBvcnRlZCI6eyJqd3RfdnBfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiJdfSwiand0X3ZjX2pzb24iOnsiYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiXX19LCJyZXF1ZXN0X29iamVjdF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVTMjU2Il0sInByZXNlbnRhdGlvbl9kZWZpbml0aW9uX3VyaV9zdXBwb3J0ZWQiOmZhbHNlLCJpYXQiOjE2ODcyODExOTUsImV4cCI6MTY4NzI4ODM5NX0.OTuPik6p3o9j6VOx-uCyxRvHwoh1pDiiZcBQFNQt2uE3dK-8izGNflJVETi_uhGSZOf25Enkq-UvEin9NrbJNw";
6
+ const rp = new RelyingPartySolution(
7
+ "http://rp.example",
8
+ walletInstanceAttestation
9
+ );
10
+ describe("decodeAuthRequestQR", () => {
11
+ it("should return authentication request URL", async () => {
12
+ const qrcode =
13
+ "ZXVkaXc6Ly9hdXRob3JpemU/Y2xpZW50X2lkPWh0dHBzOi8vdmVyaWZpZXIuZXhhbXBsZS5vcmcmcmVxdWVzdF91cmk9aHR0cHM6Ly92ZXJpZmllci5leGFtcGxlLm9yZy9yZXF1ZXN0X3VyaQ==";
14
+ const result = rp.decodeAuthRequestQR(qrcode);
15
+ expect(result).toEqual("https://verifier.example.org/request_uri");
16
+ });
17
+ it("should throw exception with invalid QR", async () => {
18
+ const qrcode = "aHR0cDovL2dvb2dsZS5pdA==";
19
+ expect(() => rp.decodeAuthRequestQR(qrcode)).toThrowError(
20
+ AuthRequestDecodeError
21
+ );
22
+ });
23
+ });
@@ -0,0 +1,150 @@
1
+ import { AuthRequestDecodeError, IoWalletError } from "../utils/errors";
2
+ import {
3
+ decode as decodeJwt,
4
+ decodeBase64,
5
+ sha256ToBase64,
6
+ SignJWT,
7
+ } from "@pagopa/io-react-native-jwt";
8
+ import { RequestObject, RpEntityConfiguration } from "./types";
9
+
10
+ import uuid from "react-native-uuid";
11
+ import type { JWK } from "@pagopa/io-react-native-jwt/lib/typescript/types";
12
+
13
+ export class RelyingPartySolution {
14
+ relyingPartyBaseUrl: string;
15
+ walletInstanceAttestation: string;
16
+ appFetch: GlobalFetch["fetch"];
17
+
18
+ constructor(
19
+ relyingPartyBaseUrl: string,
20
+ walletInstanceAttestation: string,
21
+ appFetch: GlobalFetch["fetch"] = fetch
22
+ ) {
23
+ this.relyingPartyBaseUrl = relyingPartyBaseUrl;
24
+ this.walletInstanceAttestation = walletInstanceAttestation;
25
+ this.appFetch = appFetch;
26
+ }
27
+
28
+ /**
29
+ * Decode a QR code content to an authentication request url.
30
+ * @function
31
+ * @param qrcode QR code content
32
+ *
33
+ * @returns The authentication request url
34
+ *
35
+ */
36
+ decodeAuthRequestQR(qrcode: string): string {
37
+ try {
38
+ const decoded = decodeBase64(qrcode);
39
+ const decodedUrl = new URL(decoded);
40
+ const requestUri = decodedUrl.searchParams.get("request_uri");
41
+ if (requestUri) {
42
+ return requestUri;
43
+ } else {
44
+ throw new AuthRequestDecodeError(
45
+ "Unable to obtain request_uri from QR code",
46
+ `${decodedUrl}`
47
+ );
48
+ }
49
+ } catch {
50
+ throw new AuthRequestDecodeError(
51
+ "Unable to decode QR code authentication request url",
52
+ qrcode
53
+ );
54
+ }
55
+ }
56
+ /**
57
+ * Obtain the unsigned wallet instance DPoP for authentication request
58
+ *
59
+ * @function
60
+ * @param walletInstanceAttestationJwk JWT of the Wallet Instance Attestation
61
+ * @param authRequestUrl authentication request url
62
+ *
63
+ * @returns The unsigned wallet instance DPoP
64
+ *
65
+ */
66
+ async getUnsignedWalletInstanceDPoP(
67
+ walletInstanceAttestationJwk: JWK,
68
+ authRequestUrl: string
69
+ ): Promise<string> {
70
+ return await new SignJWT({
71
+ jti: `${uuid.v4()}`,
72
+ htm: "GET",
73
+ htu: authRequestUrl,
74
+ ath: await sha256ToBase64(this.walletInstanceAttestation),
75
+ })
76
+ .setProtectedHeader({
77
+ alg: "ES256",
78
+ jwk: walletInstanceAttestationJwk,
79
+ typ: "dpop+jwt",
80
+ })
81
+ .setIssuedAt()
82
+ .setExpirationTime("1h")
83
+ .toSign();
84
+ }
85
+
86
+ /**
87
+ * Obtain the Request Object for RP authentication
88
+ *
89
+ * @function
90
+ * @param signedWalletInstanceDPoP JWT of the Wallet Instance Attestation DPoP
91
+ *
92
+ * @returns The Request Object JWT
93
+ *
94
+ */
95
+ async getRequestObject(
96
+ signedWalletInstanceDPoP: string
97
+ ): Promise<RequestObject> {
98
+ const decodedJwtDPop = await decodeJwt(signedWalletInstanceDPoP);
99
+ const requestUri = decodedJwtDPop.payload.htu as string;
100
+
101
+ const response = await this.appFetch(requestUri, {
102
+ method: "GET",
103
+ headers: {
104
+ Authorization: `DPoP ${this.walletInstanceAttestation}`,
105
+ DPoP: signedWalletInstanceDPoP,
106
+ },
107
+ });
108
+
109
+ if (response.status === 200) {
110
+ const responseText = await response.text();
111
+ const responseJwt = await decodeJwt(responseText);
112
+ const requestObj = RequestObject.parse({
113
+ header: responseJwt.protectedHeader,
114
+ payload: responseJwt.payload,
115
+ });
116
+ return requestObj;
117
+ }
118
+
119
+ throw new IoWalletError(
120
+ `Unable to obtain Request Object. Response code: ${response.status}`
121
+ );
122
+ }
123
+
124
+ /**
125
+ * Obtain the relying party entity configuration.
126
+ */
127
+ async getEntityConfiguration(): Promise<RpEntityConfiguration> {
128
+ const wellKnownUrl = new URL(
129
+ "/.well-known/openid-federation",
130
+ this.relyingPartyBaseUrl
131
+ ).href;
132
+
133
+ const response = await this.appFetch(wellKnownUrl, {
134
+ method: "GET",
135
+ });
136
+
137
+ if (response.status === 200) {
138
+ const responseText = await response.text();
139
+ const responseJwt = await decodeJwt(responseText);
140
+ return RpEntityConfiguration.parse({
141
+ header: responseJwt.protectedHeader,
142
+ payload: responseJwt.payload,
143
+ });
144
+ }
145
+
146
+ throw new IoWalletError(
147
+ `Unable to obtain RP Entity Configuration. Response code: ${response.status}`
148
+ );
149
+ }
150
+ }
@@ -0,0 +1,64 @@
1
+ import { JWK } from "../utils/jwk";
2
+ import { UnixTime } from "../sd-jwt/types";
3
+ import * as z from "zod";
4
+
5
+ export type RequestObject = z.infer<typeof RequestObject>;
6
+ export const RequestObject = z.object({
7
+ header: z.object({
8
+ typ: z.literal("JWT"),
9
+ alg: z.string(),
10
+ kid: z.string(),
11
+ trust_chain: z.array(z.string()),
12
+ }),
13
+ payload: z.object({
14
+ iss: z.string(),
15
+ iat: UnixTime,
16
+ exp: UnixTime,
17
+ state: z.string(),
18
+ nonce: z.string(),
19
+ response_uri: z.string(),
20
+ response_type: z.literal("vp_token"),
21
+ response_mode: z.literal("direct_post.jwt"),
22
+ client_id: z.string(),
23
+ client_id_scheme: z.literal("entity_id"),
24
+ scope: z.string(),
25
+ }),
26
+ });
27
+
28
+ // TODO: This types is WIP in technical rules
29
+ export type RpEntityConfiguration = z.infer<typeof RpEntityConfiguration>;
30
+ export const RpEntityConfiguration = z.object({
31
+ header: z.object({
32
+ typ: z.literal("entity-statement+jwt"),
33
+ alg: z.string(),
34
+ kid: z.string(),
35
+ }),
36
+ payload: z.object({
37
+ exp: UnixTime,
38
+ iat: UnixTime,
39
+ iss: z.string(),
40
+ sub: z.string(),
41
+ jwks: z.object({
42
+ keys: z.array(JWK),
43
+ }),
44
+ metadata: z.object({
45
+ wallet_relying_party: z.object({
46
+ application_type: z.string(),
47
+ client_id: z.string(),
48
+ client_name: z.string(),
49
+ jwks: z.object({
50
+ keys: z.array(JWK),
51
+ }),
52
+ contacts: z.array(z.string()),
53
+ }),
54
+ federation_entity: z.object({
55
+ organization_name: z.string(),
56
+ homepage_uri: z.string(),
57
+ policy_uri: z.string(),
58
+ logo_uri: z.string(),
59
+ contacts: z.array(z.string()),
60
+ }),
61
+ }),
62
+ authority_hints: z.array(z.string()),
63
+ }),
64
+ });
@@ -0,0 +1,25 @@
1
+ import * as z from "zod";
2
+
3
+ import { SignJWT } from "@pagopa/io-react-native-jwt";
4
+ import type { JWK } from "./jwk";
5
+
6
+ export const getUnsignedDPop = (jwk: JWK, payload: DPoPPayload): string => {
7
+ const dPop = new SignJWT(payload)
8
+ .setProtectedHeader({
9
+ alg: "ES256",
10
+ typ: "dpop+jwt",
11
+ jwk,
12
+ })
13
+ .setIssuedAt()
14
+ .setExpirationTime("1h")
15
+ .toSign();
16
+ return dPop;
17
+ };
18
+
19
+ export type DPoPPayload = z.infer<typeof DPoPPayload>;
20
+ export const DPoPPayload = z.object({
21
+ jti: z.string(),
22
+ htm: z.union([z.literal("POST"), z.literal("GET")]),
23
+ htu: z.string(),
24
+ ath: z.string(),
25
+ });
@@ -72,3 +72,27 @@ export class WalletInstanceAttestationIssuingError extends IoWalletError {
72
72
  this.reason = reason;
73
73
  }
74
74
  }
75
+
76
+ /**
77
+ * An error subclass thrown when auth request decode fail
78
+ *
79
+ */
80
+ export class AuthRequestDecodeError extends IoWalletError {
81
+ static get code(): "ERR_IO_WALLET_AUTHENTICATION_REQUEST_DECODE_FAILED" {
82
+ return "ERR_IO_WALLET_AUTHENTICATION_REQUEST_DECODE_FAILED";
83
+ }
84
+
85
+ code = "ERR_IO_WALLET_AUTHENTICATION_REQUEST_DECODE_FAILED";
86
+
87
+ /** The Claim for which the validation failed. */
88
+ claim: string;
89
+
90
+ /** Reason code for the validation failure. */
91
+ reason: string;
92
+
93
+ constructor(message: string, claim = "unspecified", reason = "unspecified") {
94
+ super(message);
95
+ this.claim = claim;
96
+ this.reason = reason;
97
+ }
98
+ }
@@ -0,0 +1,4 @@
1
+ import { SignJWT } from "@pagopa/io-react-native-jwt";
2
+
3
+ export const getSignedJwt = async (unsignedJwt: string, signature: string) =>
4
+ await SignJWT.appendSignature(unsignedJwt, signature);
@@ -8,9 +8,13 @@ import { WalletInstanceAttestationIssuingError } from "../utils/errors";
8
8
 
9
9
  export class Issuing {
10
10
  walletProviderBaseUrl: string;
11
-
12
- constructor(walletProviderBaseUrl: string) {
11
+ appFetch: GlobalFetch["fetch"];
12
+ constructor(
13
+ walletProviderBaseUrl: string,
14
+ appFetch: GlobalFetch["fetch"] = fetch
15
+ ) {
13
16
  this.walletProviderBaseUrl = walletProviderBaseUrl;
17
+ this.appFetch = appFetch;
14
18
  }
15
19
 
16
20
  /**
@@ -58,15 +62,13 @@ export class Issuing {
58
62
  * @param attestationRequest Wallet Instance Attestaion Request
59
63
  * obtained with {@link getAttestationRequestToSign}
60
64
  * @param signature Signature of the Wallet Instance Attestaion Request
61
- * @param appFetch Optional object with fetch function to use
62
65
  *
63
66
  * @returns {string} Wallet Instance Attestation
64
67
  *
65
68
  */
66
69
  async getAttestation(
67
70
  attestationRequest: string,
68
- signature: string,
69
- appFetch: GlobalFetch = { fetch }
71
+ signature: string
70
72
  ): Promise<String> {
71
73
  const signedAttestationRequest = await SignJWT.appendSignature(
72
74
  attestationRequest,
@@ -87,7 +89,7 @@ export class Issuing {
87
89
  "urn:ietf:params:oauth:client-assertion-type:jwt-key-attestation",
88
90
  assertion: signedAttestationRequest,
89
91
  };
90
- const response = await appFetch.fetch(tokenUrl, {
92
+ const response = await this.appFetch(tokenUrl, {
91
93
  method: "POST",
92
94
  headers: {
93
95
  "Content-Type": "application/json",