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

Sign up to get free protection for your applications and to get access to all the features.
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
+ });