@pagopa/io-react-native-wallet 0.1.0 → 0.2.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.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/index.js +12 -5
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/pid/index.js +7 -0
  5. package/lib/commonjs/pid/index.js.map +1 -1
  6. package/lib/commonjs/pid/issuing.js +231 -0
  7. package/lib/commonjs/pid/issuing.js.map +1 -0
  8. package/lib/commonjs/rp/__test__/index.test.js +18 -0
  9. package/lib/commonjs/rp/__test__/index.test.js.map +1 -0
  10. package/lib/commonjs/rp/index.js +116 -0
  11. package/lib/commonjs/rp/index.js.map +1 -0
  12. package/lib/commonjs/rp/types.js +72 -0
  13. package/lib/commonjs/rp/types.js.map +1 -0
  14. package/lib/commonjs/sd-jwt/types.js +1 -1
  15. package/lib/commonjs/sd-jwt/types.js.map +1 -1
  16. package/lib/commonjs/utils/dpop.js +27 -0
  17. package/lib/commonjs/utils/dpop.js.map +1 -0
  18. package/lib/commonjs/utils/errors.js +49 -1
  19. package/lib/commonjs/utils/errors.js.map +1 -1
  20. package/lib/commonjs/wallet-instance-attestation/issuing.js +3 -5
  21. package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -1
  22. package/lib/module/index.js +4 -4
  23. package/lib/module/index.js.map +1 -1
  24. package/lib/module/pid/index.js +2 -1
  25. package/lib/module/pid/index.js.map +1 -1
  26. package/lib/module/pid/issuing.js +225 -0
  27. package/lib/module/pid/issuing.js.map +1 -0
  28. package/lib/module/rp/__test__/index.test.js +16 -0
  29. package/lib/module/rp/__test__/index.test.js.map +1 -0
  30. package/lib/module/rp/index.js +108 -0
  31. package/lib/module/rp/index.js.map +1 -0
  32. package/lib/module/rp/types.js +63 -0
  33. package/lib/module/rp/types.js.map +1 -0
  34. package/lib/module/sd-jwt/types.js +1 -1
  35. package/lib/module/sd-jwt/types.js.map +1 -1
  36. package/lib/module/utils/dpop.js +17 -0
  37. package/lib/module/utils/dpop.js.map +1 -0
  38. package/lib/module/utils/errors.js +46 -0
  39. package/lib/module/utils/errors.js.map +1 -1
  40. package/lib/module/wallet-instance-attestation/issuing.js +3 -5
  41. package/lib/module/wallet-instance-attestation/issuing.js.map +1 -1
  42. package/lib/typescript/index.d.ts +4 -2
  43. package/lib/typescript/index.d.ts.map +1 -1
  44. package/lib/typescript/pid/index.d.ts +2 -1
  45. package/lib/typescript/pid/index.d.ts.map +1 -1
  46. package/lib/typescript/pid/issuing.d.ts +93 -0
  47. package/lib/typescript/pid/issuing.d.ts.map +1 -0
  48. package/lib/typescript/rp/__test__/index.test.d.ts +2 -0
  49. package/lib/typescript/rp/__test__/index.test.d.ts.map +1 -0
  50. package/lib/typescript/rp/index.d.ts +43 -0
  51. package/lib/typescript/rp/index.d.ts.map +1 -0
  52. package/lib/typescript/rp/types.d.ts +840 -0
  53. package/lib/typescript/rp/types.d.ts.map +1 -0
  54. package/lib/typescript/sd-jwt/types.d.ts +5 -5
  55. package/lib/typescript/utils/dpop.d.ts +21 -0
  56. package/lib/typescript/utils/dpop.d.ts.map +1 -0
  57. package/lib/typescript/utils/errors.d.ts +26 -0
  58. package/lib/typescript/utils/errors.d.ts.map +1 -1
  59. package/lib/typescript/wallet-instance-attestation/issuing.d.ts +3 -3
  60. package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -1
  61. package/lib/typescript/wallet-instance-attestation/types.d.ts +4 -4
  62. package/package.json +4 -2
  63. package/src/index.ts +4 -5
  64. package/src/pid/index.ts +2 -1
  65. package/src/pid/issuing.ts +305 -0
  66. package/src/rp/__test__/index.test.ts +23 -0
  67. package/src/rp/index.ts +150 -0
  68. package/src/rp/types.ts +64 -0
  69. package/src/sd-jwt/types.ts +1 -1
  70. package/src/utils/dpop.ts +25 -0
  71. package/src/utils/errors.ts +48 -0
  72. package/src/wallet-instance-attestation/issuing.ts +9 -7
@@ -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"}
@@ -22,18 +22,18 @@ export declare const SdJwt4VC: z.ZodObject<{
22
22
  header: z.ZodObject<{
23
23
  typ: z.ZodLiteral<"vc+sd-jwt">;
24
24
  alg: z.ZodString;
25
- kid: z.ZodString;
25
+ kid: z.ZodOptional<z.ZodString>;
26
26
  trust_chain: z.ZodArray<z.ZodString, "many">;
27
27
  }, "strip", z.ZodTypeAny, {
28
28
  alg: string;
29
- kid: string;
30
29
  typ: "vc+sd-jwt";
31
30
  trust_chain: string[];
31
+ kid?: string | undefined;
32
32
  }, {
33
33
  alg: string;
34
- kid: string;
35
34
  typ: "vc+sd-jwt";
36
35
  trust_chain: string[];
36
+ kid?: string | undefined;
37
37
  }>;
38
38
  payload: z.ZodObject<{
39
39
  iss: z.ZodString;
@@ -307,9 +307,9 @@ export declare const SdJwt4VC: z.ZodObject<{
307
307
  }, "strip", z.ZodTypeAny, {
308
308
  header: {
309
309
  alg: string;
310
- kid: string;
311
310
  typ: "vc+sd-jwt";
312
311
  trust_chain: string[];
312
+ kid?: string | undefined;
313
313
  };
314
314
  payload: {
315
315
  type: "PersonIdentificationData";
@@ -361,9 +361,9 @@ export declare const SdJwt4VC: z.ZodObject<{
361
361
  }, {
362
362
  header: {
363
363
  alg: string;
364
- kid: string;
365
364
  typ: "vc+sd-jwt";
366
365
  trust_chain: string[];
366
+ kid?: string | undefined;
367
367
  };
368
368
  payload: {
369
369
  type: "PersonIdentificationData";
@@ -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.ZodOptional<z.ZodString>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ jti: string;
12
+ htm: "POST" | "GET";
13
+ htu: string;
14
+ ath?: string | undefined;
15
+ }, {
16
+ jti: string;
17
+ htm: "POST" | "GET";
18
+ htu: string;
19
+ ath?: string | undefined;
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,30 @@ 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
+ }
58
+ /**
59
+ * An error subclass thrown when validation fail
60
+ *
61
+ */
62
+ export declare class PidIssuingError extends IoWalletError {
63
+ static get code(): "ERR_IO_WALLET_PID_ISSUING_FAILED";
64
+ code: string;
65
+ /** The Claim for which the validation failed. */
66
+ claim: string;
67
+ /** Reason code for the validation failure. */
68
+ reason: string;
69
+ constructor(message: string, claim?: string, reason?: string);
70
+ }
45
71
  //# 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;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,aAAa;IAChD,MAAM,KAAK,IAAI,IAAI,kCAAkC,CAEpD;IAED,IAAI,SAAsC;IAE1C,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,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.2.0",
4
4
  "description": "Provide data structures, helpers and API for IO Wallet",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -66,13 +66,15 @@
66
66
  "react": "18.2.0",
67
67
  "react-native": "0.71.8",
68
68
  "react-native-builder-bob": "^0.20.0",
69
- "typescript": "^5.0.2"
69
+ "typescript": "^5.0.2",
70
+ "@pagopa/io-react-native-crypto": "^0.2.3"
70
71
  },
71
72
  "resolutions": {
72
73
  "@types/react": "17.0.21"
73
74
  },
74
75
  "peerDependencies": {
75
76
  "@pagopa/io-react-native-jwt": "*",
77
+ "@pagopa/io-react-native-crypto": "*",
76
78
  "react": "*",
77
79
  "react-native": "*"
78
80
  },
package/src/index.ts CHANGED
@@ -1,8 +1,7 @@
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";
3
6
 
4
- export function multiply(a: number, b: number): Promise<number> {
5
- return Promise.resolve(a * b);
6
- }
7
-
8
- export { PID, WalletInstanceAttestation };
7
+ export { PID, RP, WalletInstanceAttestation, Errors, getUnsignedDPop };
package/src/pid/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import * as SdJwt from "./sd-jwt";
2
- export { SdJwt };
2
+ import { Issuing } from "./issuing";
3
+ export { SdJwt, Issuing };
@@ -0,0 +1,305 @@
1
+ import {
2
+ decode as decodeJwt,
3
+ sha256ToBase64,
4
+ } from "@pagopa/io-react-native-jwt";
5
+
6
+ import { SignJWT, thumbprint } from "@pagopa/io-react-native-jwt";
7
+ import { JWK } from "../utils/jwk";
8
+ import uuid from "react-native-uuid";
9
+ import { PidIssuingError } from "../utils/errors";
10
+ import { getUnsignedDPop } from "../utils/dpop";
11
+ import { sign, generate, deleteKey } from "@pagopa/io-react-native-crypto";
12
+
13
+ // This is a temporary type that will be used for demo purposes only
14
+ export type CieData = {
15
+ birthDate: string;
16
+ fiscalCode: string;
17
+ name: string;
18
+ surname: string;
19
+ };
20
+
21
+ export type TokenResponse = { access_token: string; c_nonce: string };
22
+ export type PidResponse = {
23
+ credential: string;
24
+ c_nonce: string;
25
+ c_nonce_expires_in: number;
26
+ format: string;
27
+ };
28
+
29
+ export class Issuing {
30
+ pidProviderBaseUrl: string;
31
+ walletProviderBaseUrl: string;
32
+ walletInstanceAttestation: string;
33
+ codeVerifier: string;
34
+ clientId: string;
35
+ state: string;
36
+ authorizationCode: string;
37
+ appFetch: GlobalFetch["fetch"];
38
+
39
+ constructor(
40
+ pidProviderBaseUrl: string,
41
+ walletProviderBaseUrl: string,
42
+ walletInstanceAttestation: string,
43
+ clientId: string,
44
+ appFetch: GlobalFetch["fetch"] = fetch
45
+ ) {
46
+ this.pidProviderBaseUrl = pidProviderBaseUrl;
47
+ this.walletProviderBaseUrl = walletProviderBaseUrl;
48
+ this.state = `${uuid.v4()}`;
49
+ this.codeVerifier = `${uuid.v4()}`;
50
+ this.authorizationCode = `${uuid.v4()}`;
51
+ this.walletInstanceAttestation = walletInstanceAttestation;
52
+ this.clientId = clientId;
53
+ this.appFetch = appFetch;
54
+ }
55
+
56
+ /**
57
+ * Return the unsigned jwt to call the PAR request.
58
+ *
59
+ * @function
60
+ * @param jwk The wallet instance attestation public JWK
61
+ *
62
+ * @returns Unsigned jwt
63
+ *
64
+ */
65
+ async getUnsignedJwtForPar(jwk: JWK): Promise<string> {
66
+ const parsedJwk = JWK.parse(jwk);
67
+ const keyThumbprint = await thumbprint(parsedJwk);
68
+ const publicKey = { ...parsedJwk, kid: keyThumbprint };
69
+ const codeChallenge = await sha256ToBase64(this.codeVerifier);
70
+
71
+ const unsignedJwtForPar = new SignJWT({
72
+ client_assertion_type:
73
+ "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
74
+ authorization_details: [
75
+ {
76
+ credentialDefinition: {
77
+ type: ["eu.eudiw.pid.it"],
78
+ },
79
+ format: "vc+sd-jwt",
80
+ type: "type",
81
+ },
82
+ ],
83
+ response_type: "code",
84
+ code_challenge_method: "s256",
85
+ redirect_uri: this.walletProviderBaseUrl,
86
+ state: this.state,
87
+ client_id: this.clientId,
88
+ code_challenge: codeChallenge,
89
+ })
90
+ .setProtectedHeader({
91
+ alg: "ES256",
92
+ kid: publicKey.kid,
93
+ })
94
+ .setIssuedAt()
95
+ .setExpirationTime("1h")
96
+ .toSign();
97
+
98
+ return unsignedJwtForPar;
99
+ }
100
+
101
+ /**
102
+ * Make a PAR request to the PID issuer and return the response url
103
+ *
104
+ * @function
105
+ * @param unsignedJwtForPar The unsigned JWT for PAR
106
+ * @param signature The JWT for PAR signature
107
+ *
108
+ * @returns Unsigned PAR url
109
+ *
110
+ */
111
+ async getPar(unsignedJwtForPar: string, signature: string): Promise<string> {
112
+ const codeChallenge = await sha256ToBase64(this.codeVerifier);
113
+ const signedJwtForPar = await SignJWT.appendSignature(
114
+ unsignedJwtForPar,
115
+ signature
116
+ );
117
+
118
+ const parUrl = new URL("/as/par", this.pidProviderBaseUrl).href;
119
+
120
+ const requestBody = {
121
+ response_type: "code",
122
+ client_id: this.clientId,
123
+ code_challenge: codeChallenge,
124
+ code_challenge_method: "S256",
125
+ client_assertion_type:
126
+ "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
127
+ client_assertion: this.walletInstanceAttestation,
128
+ request: signedJwtForPar,
129
+ };
130
+
131
+ var formBody = new URLSearchParams(requestBody);
132
+
133
+ const response = await this.appFetch(parUrl, {
134
+ method: "POST",
135
+ headers: {
136
+ "Content-Type": "application/x-www-form-urlencoded",
137
+ },
138
+ body: formBody.toString(),
139
+ });
140
+
141
+ if (response.status === 201) {
142
+ const result = await response.json();
143
+ return result.request_uri;
144
+ }
145
+
146
+ throw new PidIssuingError(
147
+ `Unable to obtain PAR. Response code: ${await response.text()}`
148
+ );
149
+ }
150
+
151
+ /**
152
+ * Return the unsigned jwt for a generic DPoP
153
+ *
154
+ * @function
155
+ * @param jwk the public key for which the DPoP is to be created
156
+ *
157
+ * @returns Unsigned JWT for DPoP
158
+ *
159
+ */
160
+ async getUnsignedDPoP(jwk: JWK): Promise<string> {
161
+ const tokenUrl = new URL("/token", this.pidProviderBaseUrl).href;
162
+ const dPop = getUnsignedDPop(jwk, {
163
+ htm: "POST",
164
+ htu: tokenUrl,
165
+ jti: `${uuid.v4()}`,
166
+ });
167
+ return dPop;
168
+ }
169
+
170
+ /**
171
+ * Make an auth token request to the PID issuer
172
+ *
173
+ * @function
174
+ * @returns a token response
175
+ *
176
+ */
177
+ async getAuthToken(): Promise<TokenResponse> {
178
+ //Generate fresh keys for DPoP
179
+ const dPopKeyTag = `${uuid.v4()}`;
180
+ const dPopKey = await generate(dPopKeyTag);
181
+ const unsignedDPopForToken = await this.getUnsignedDPoP(dPopKey);
182
+ const dPopTokenSignature = await sign(unsignedDPopForToken, dPopKeyTag);
183
+ await deleteKey(dPopKeyTag);
184
+
185
+ const signedDPop = await SignJWT.appendSignature(
186
+ unsignedDPopForToken,
187
+ dPopTokenSignature
188
+ );
189
+ const decodedJwtDPop = decodeJwt(signedDPop);
190
+ const tokenUrl = decodedJwtDPop.payload.htu as string;
191
+ const requestBody = {
192
+ grant_type: "authorization code",
193
+ client_id: this.clientId,
194
+ code: this.authorizationCode,
195
+ code_verifier: this.codeVerifier,
196
+ client_assertion_type:
197
+ "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
198
+ client_assertion: this.walletInstanceAttestation,
199
+ redirect_uri: this.walletProviderBaseUrl,
200
+ };
201
+ var formBody = new URLSearchParams(requestBody);
202
+
203
+ const response = await this.appFetch(tokenUrl, {
204
+ method: "POST",
205
+ headers: {
206
+ "Content-Type": "application/x-www-form-urlencoded",
207
+ DPoP: signedDPop,
208
+ },
209
+ body: formBody.toString(),
210
+ });
211
+
212
+ if (response.status === 200) {
213
+ return await response.json();
214
+ }
215
+
216
+ throw new PidIssuingError(
217
+ `Unable to obtain token. Response code: ${await response.text()}`
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Return the unsigned jwt for nonce proof of possession
223
+ *
224
+ * @function
225
+ * @param nonce the nonce
226
+ *
227
+ * @returns Unsigned JWT for nonce proof
228
+ *
229
+ */
230
+ async getUnsignedNonceProof(nonce: string): Promise<string> {
231
+ const unsignedProof = new SignJWT({
232
+ nonce,
233
+ })
234
+ .setProtectedHeader({
235
+ alg: "ES256",
236
+ type: "openid4vci-proof+jwt",
237
+ })
238
+ .setAudience(this.walletProviderBaseUrl)
239
+ .setIssuer(this.clientId)
240
+ .setIssuedAt()
241
+ .setExpirationTime("1h")
242
+ .toSign();
243
+ return unsignedProof;
244
+ }
245
+
246
+ /**
247
+ * Make the credential issuing request to the PID issuer
248
+ *
249
+ * @function
250
+ * @param unsignedDPopForPid The unsigned JWT for PID DPoP
251
+ * @param dPopPidSignature The JWT for PID DPoP signature
252
+ * @param unsignedNonceProof The unsigned JWT for nonce proof
253
+ * @param nonceProofSignature The JWT for nonce proof signature
254
+ * @param accessToken The access token obtained with getAuthToken
255
+ * @param cieData Personal data read by the CIE
256
+ *
257
+ * @returns a credential
258
+ *
259
+ */
260
+ async getCredential(
261
+ unsignedDPopForPid: string,
262
+ dPopPidSignature: string,
263
+ unsignedNonceProof: string,
264
+ nonceProofSignature: string,
265
+ accessToken: string,
266
+ cieData: CieData
267
+ ): Promise<PidResponse> {
268
+ const signedDPopForPid = await SignJWT.appendSignature(
269
+ unsignedDPopForPid,
270
+ dPopPidSignature
271
+ );
272
+ const signedNonceProof = await SignJWT.appendSignature(
273
+ unsignedNonceProof,
274
+ nonceProofSignature
275
+ );
276
+ const credentialUrl = new URL("/credential", this.pidProviderBaseUrl).href;
277
+
278
+ const requestBody = {
279
+ credential_definition: JSON.stringify({ type: ["eu.eudiw.pid.it"] }),
280
+ format: "vc+sd-jwt",
281
+ proof: JSON.stringify({
282
+ jwt: signedNonceProof,
283
+ cieData,
284
+ proof_type: "jwt",
285
+ }),
286
+ };
287
+ const formBody = new URLSearchParams(requestBody);
288
+
289
+ const response = await this.appFetch(credentialUrl, {
290
+ method: "POST",
291
+ headers: {
292
+ "Content-Type": "application/x-www-form-urlencoded",
293
+ DPoP: signedDPopForPid,
294
+ Authorization: accessToken,
295
+ },
296
+ body: formBody.toString(),
297
+ });
298
+
299
+ if (response.status === 200) {
300
+ return await response.json();
301
+ }
302
+
303
+ throw new PidIssuingError(`Unable to obtain credential!`);
304
+ }
305
+ }
@@ -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
+ });