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

Sign up to get free protection for your applications and to get access to all the features.
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",