@keeper-security/keeperapi 16.0.0 → 16.0.3
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.
- package/.idea/keeperapi.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/5e18f43a9b613f6f6f2302b3a4e5176f6bc92fc5 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/61937b699b545d77d9bb72af5e7182c1803ae24c +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/7fbbd271f2a6fe2a55d7ee5e3ad7716e7cf051ba +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/85bbe002887f4018a0fe647b8b05194dbc048f66 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/8f851753b53908ad3f972c31696dbdeeed9b4661 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/9eb60cc6282da763987e9a366716c57e69db7cbc +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/dc4d6f4549ac6f4017ff017e35d2349480068cdf +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/e4d5be0687b96b93a032d9922fa511f04ed27deb +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/code/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/5e18f43a9b613f6f6f2302b3a4e5176f6bc92fc5 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/61937b699b545d77d9bb72af5e7182c1803ae24c +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/7fbbd271f2a6fe2a55d7ee5e3ad7716e7cf051ba +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/85bbe002887f4018a0fe647b8b05194dbc048f66 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/8f851753b53908ad3f972c31696dbdeeed9b4661 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/9eb60cc6282da763987e9a366716c57e69db7cbc +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/dc4d6f4549ac6f4017ff017e35d2349480068cdf +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/e4d5be0687b96b93a032d9922fa511f04ed27deb +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/semanticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/5e18f43a9b613f6f6f2302b3a4e5176f6bc92fc5 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/61937b699b545d77d9bb72af5e7182c1803ae24c +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/7fbbd271f2a6fe2a55d7ee5e3ad7716e7cf051ba +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/85bbe002887f4018a0fe647b8b05194dbc048f66 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/8f851753b53908ad3f972c31696dbdeeed9b4661 +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/9eb60cc6282da763987e9a366716c57e69db7cbc +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/dc4d6f4549ac6f4017ff017e35d2349480068cdf +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/e4d5be0687b96b93a032d9922fa511f04ed27deb +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/syntacticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/24fbc0427075baf3ac3fee2ada4ddd2fdd6804a6 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/3050043c8485297b366404c9b699f00a98a44b3c +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/4dffa8599530c3200ba2fa8029fa291435ba7cf7 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/6a0bc58668c059b99bff8dba6f0246cb049f0db9 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/7351d2ef4cb3d5388301a3ad1d1f7e3a0782c0bd +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/8d7296121e0007eebc1b0eabcfcc2a262d6bbc22 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/8fe39fe93705cfe38c1944a307c3fd64e5985d1e +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/9f92f7bfd4bd0aa870a95101ec02f2a32337ff1f +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/a6e317ef3069e9a270811fbc729535be3c405f41 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/ac8bef3228680d10f4db046facede43040f41854 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/afe32918d3a600939f39f4fcfb6852fe43f8ada9 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/bbe22fc71946abdfc667c2388606bfe83397ec81 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/d7bc52f98e9a008b81c621d963e9d4a276c80ee3 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/ddcd4d72185f8c85750f6f2f755c1152fddafdf4 +0 -0
- package/.rpt2_cache/rpt2_02b50c05ca0c5f1826efd221b9443199179ac6f1/types/cache/df632d4bb144fc3001f92ea2a2678baeb386dcc4 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/0155dc333b076ed1526d900b68620ead8c8d8b6b +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/09a21931f2a982e751cd2b7ce45fa6df0bfdbfc6 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/0bd8fcd9e5871476984908e9d214bc12244a56c7 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/4af634b56884c8fd08ba3107422b0108644ee513 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/624184538e182d7e8888620f356c12b51bbcc6ca +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/67074a8d808b8e4a0c15d67f36f13664fcff8143 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/934e86e88e5eef117e7f7c7e98bb7b13ee83e8af +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/a282f7f4f34b6e0f7604a1e31cac2d2efbc0304c +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/b1af8b4bca5d49b190d355a5d7186b277280db7e +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/b5f1f1702282c76ceff0f0ff97a3ba80b5adeccc +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/bcfb396489824911797b349d7388000f2b3a3298 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/f2e98088f53c88114a0a5322154f96a639246440 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/code/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/0155dc333b076ed1526d900b68620ead8c8d8b6b +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/09a21931f2a982e751cd2b7ce45fa6df0bfdbfc6 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/0bd8fcd9e5871476984908e9d214bc12244a56c7 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/4af634b56884c8fd08ba3107422b0108644ee513 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/624184538e182d7e8888620f356c12b51bbcc6ca +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/67074a8d808b8e4a0c15d67f36f13664fcff8143 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/934e86e88e5eef117e7f7c7e98bb7b13ee83e8af +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/a282f7f4f34b6e0f7604a1e31cac2d2efbc0304c +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/b1af8b4bca5d49b190d355a5d7186b277280db7e +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/b5f1f1702282c76ceff0f0ff97a3ba80b5adeccc +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/bcfb396489824911797b349d7388000f2b3a3298 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/f2e98088f53c88114a0a5322154f96a639246440 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/semanticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/0155dc333b076ed1526d900b68620ead8c8d8b6b +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/09a21931f2a982e751cd2b7ce45fa6df0bfdbfc6 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/0bd8fcd9e5871476984908e9d214bc12244a56c7 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/4af634b56884c8fd08ba3107422b0108644ee513 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/624184538e182d7e8888620f356c12b51bbcc6ca +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/67074a8d808b8e4a0c15d67f36f13664fcff8143 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/934e86e88e5eef117e7f7c7e98bb7b13ee83e8af +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/a282f7f4f34b6e0f7604a1e31cac2d2efbc0304c +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/b1af8b4bca5d49b190d355a5d7186b277280db7e +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/b5f1f1702282c76ceff0f0ff97a3ba80b5adeccc +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/bcfb396489824911797b349d7388000f2b3a3298 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/f2e98088f53c88114a0a5322154f96a639246440 +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/syntacticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/24fbc0427075baf3ac3fee2ada4ddd2fdd6804a6 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/3050043c8485297b366404c9b699f00a98a44b3c +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/4dffa8599530c3200ba2fa8029fa291435ba7cf7 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/603166e7191a1eb2b59e6dc3a0c5060e83e42bf5 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/6a0bc58668c059b99bff8dba6f0246cb049f0db9 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/7351d2ef4cb3d5388301a3ad1d1f7e3a0782c0bd +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/8d7296121e0007eebc1b0eabcfcc2a262d6bbc22 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/8fe39fe93705cfe38c1944a307c3fd64e5985d1e +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/9f92f7bfd4bd0aa870a95101ec02f2a32337ff1f +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/a6e317ef3069e9a270811fbc729535be3c405f41 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/ac8bef3228680d10f4db046facede43040f41854 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/afe32918d3a600939f39f4fcfb6852fe43f8ada9 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/bbe22fc71946abdfc667c2388606bfe83397ec81 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/d7bc52f98e9a008b81c621d963e9d4a276c80ee3 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/ddcd4d72185f8c85750f6f2f755c1152fddafdf4 +0 -0
- package/.rpt2_cache/rpt2_3297a01a1b62f1695764463c584003ad1da34817/types/cache/df632d4bb144fc3001f92ea2a2678baeb386dcc4 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/09a21931f2a982e751cd2b7ce45fa6df0bfdbfc6 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/5e18f43a9b613f6f6f2302b3a4e5176f6bc92fc5 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/624184538e182d7e8888620f356c12b51bbcc6ca +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/7fbbd271f2a6fe2a55d7ee5e3ad7716e7cf051ba +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/8378bbd69de2cb8546f7e5f380a4ca34a2b252ac +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/85bbe002887f4018a0fe647b8b05194dbc048f66 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/8f851753b53908ad3f972c31696dbdeeed9b4661 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/b5f1f1702282c76ceff0f0ff97a3ba80b5adeccc +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/bcfb396489824911797b349d7388000f2b3a3298 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/dc4d6f4549ac6f4017ff017e35d2349480068cdf +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/e4d5be0687b96b93a032d9922fa511f04ed27deb +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/f2e98088f53c88114a0a5322154f96a639246440 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/code/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/09a21931f2a982e751cd2b7ce45fa6df0bfdbfc6 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/5e18f43a9b613f6f6f2302b3a4e5176f6bc92fc5 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/624184538e182d7e8888620f356c12b51bbcc6ca +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/7fbbd271f2a6fe2a55d7ee5e3ad7716e7cf051ba +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/8378bbd69de2cb8546f7e5f380a4ca34a2b252ac +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/85bbe002887f4018a0fe647b8b05194dbc048f66 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/8f851753b53908ad3f972c31696dbdeeed9b4661 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/b5f1f1702282c76ceff0f0ff97a3ba80b5adeccc +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/bcfb396489824911797b349d7388000f2b3a3298 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/dc4d6f4549ac6f4017ff017e35d2349480068cdf +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/e4d5be0687b96b93a032d9922fa511f04ed27deb +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/f2e98088f53c88114a0a5322154f96a639246440 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/semanticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/09a21931f2a982e751cd2b7ce45fa6df0bfdbfc6 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/5e18f43a9b613f6f6f2302b3a4e5176f6bc92fc5 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/624184538e182d7e8888620f356c12b51bbcc6ca +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/7fbbd271f2a6fe2a55d7ee5e3ad7716e7cf051ba +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/8378bbd69de2cb8546f7e5f380a4ca34a2b252ac +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/85bbe002887f4018a0fe647b8b05194dbc048f66 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/8f851753b53908ad3f972c31696dbdeeed9b4661 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/b5f1f1702282c76ceff0f0ff97a3ba80b5adeccc +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/bcfb396489824911797b349d7388000f2b3a3298 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/dc4d6f4549ac6f4017ff017e35d2349480068cdf +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/e4d5be0687b96b93a032d9922fa511f04ed27deb +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/f2e98088f53c88114a0a5322154f96a639246440 +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/syntacticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/24fbc0427075baf3ac3fee2ada4ddd2fdd6804a6 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/3050043c8485297b366404c9b699f00a98a44b3c +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/4dffa8599530c3200ba2fa8029fa291435ba7cf7 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/6a0bc58668c059b99bff8dba6f0246cb049f0db9 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/7351d2ef4cb3d5388301a3ad1d1f7e3a0782c0bd +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/8d7296121e0007eebc1b0eabcfcc2a262d6bbc22 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/8fe39fe93705cfe38c1944a307c3fd64e5985d1e +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/9f92f7bfd4bd0aa870a95101ec02f2a32337ff1f +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/a6e317ef3069e9a270811fbc729535be3c405f41 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/ac8bef3228680d10f4db046facede43040f41854 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/afe32918d3a600939f39f4fcfb6852fe43f8ada9 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/bbe22fc71946abdfc667c2388606bfe83397ec81 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/d7bc52f98e9a008b81c621d963e9d4a276c80ee3 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/ddcd4d72185f8c85750f6f2f755c1152fddafdf4 +0 -0
- package/.rpt2_cache/rpt2_695cfcfdb8ad5fdc842bebc6c6523fff84b97236/types/cache/df632d4bb144fc3001f92ea2a2678baeb386dcc4 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/0155dc333b076ed1526d900b68620ead8c8d8b6b +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/0bd8fcd9e5871476984908e9d214bc12244a56c7 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/4af634b56884c8fd08ba3107422b0108644ee513 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/61937b699b545d77d9bb72af5e7182c1803ae24c +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/651b0423c46988097da560167e3f6f432e8fbfc8 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/67074a8d808b8e4a0c15d67f36f13664fcff8143 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/934e86e88e5eef117e7f7c7e98bb7b13ee83e8af +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/b1af8b4bca5d49b190d355a5d7186b277280db7e +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/code/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/0155dc333b076ed1526d900b68620ead8c8d8b6b +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/0bd8fcd9e5871476984908e9d214bc12244a56c7 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/4af634b56884c8fd08ba3107422b0108644ee513 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/61937b699b545d77d9bb72af5e7182c1803ae24c +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/651b0423c46988097da560167e3f6f432e8fbfc8 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/67074a8d808b8e4a0c15d67f36f13664fcff8143 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/934e86e88e5eef117e7f7c7e98bb7b13ee83e8af +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/b1af8b4bca5d49b190d355a5d7186b277280db7e +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/semanticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/0155dc333b076ed1526d900b68620ead8c8d8b6b +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/0bd8fcd9e5871476984908e9d214bc12244a56c7 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/1c87a75f7bda91e438f008e21dafe531c949031d +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/4af634b56884c8fd08ba3107422b0108644ee513 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/55ab809efdb0061fba3df7fa2029e2706a361534 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/61937b699b545d77d9bb72af5e7182c1803ae24c +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/651b0423c46988097da560167e3f6f432e8fbfc8 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/67074a8d808b8e4a0c15d67f36f13664fcff8143 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/6eb75399e6e0179b01b9d8cb1afc01f5068ef4f0 +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/7c0e3c33301dea7e674a558fac5e4f028dbaa3ad +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/934e86e88e5eef117e7f7c7e98bb7b13ee83e8af +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/b1af8b4bca5d49b190d355a5d7186b277280db7e +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/syntacticDiagnostics/cache/f385a84342a7d9131d8da13c2546cde25fa23f1d +1 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/24fbc0427075baf3ac3fee2ada4ddd2fdd6804a6 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/3050043c8485297b366404c9b699f00a98a44b3c +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/4dffa8599530c3200ba2fa8029fa291435ba7cf7 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/603166e7191a1eb2b59e6dc3a0c5060e83e42bf5 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/6a0bc58668c059b99bff8dba6f0246cb049f0db9 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/7351d2ef4cb3d5388301a3ad1d1f7e3a0782c0bd +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/8d7296121e0007eebc1b0eabcfcc2a262d6bbc22 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/8fe39fe93705cfe38c1944a307c3fd64e5985d1e +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/9f92f7bfd4bd0aa870a95101ec02f2a32337ff1f +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/a6e317ef3069e9a270811fbc729535be3c405f41 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/ac8bef3228680d10f4db046facede43040f41854 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/afe32918d3a600939f39f4fcfb6852fe43f8ada9 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/bbe22fc71946abdfc667c2388606bfe83397ec81 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/d7bc52f98e9a008b81c621d963e9d4a276c80ee3 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/ddcd4d72185f8c85750f6f2f755c1152fddafdf4 +0 -0
- package/.rpt2_cache/rpt2_91c74d821d2604d85061209debacd53e1a896747/types/cache/df632d4bb144fc3001f92ea2a2678baeb386dcc4 +0 -0
- package/babel.config.js +6 -0
- package/package.json +7 -10
- package/rollup.config.js +50 -0
- package/scripts/cleanDistFolder.js +9 -0
- package/src/__tests__/utils.test.js +13 -0
- package/src/auth.ts +1514 -0
- package/src/browser/asn1hex.ts +296 -0
- package/src/browser/index.ts +17 -0
- package/src/browser/jsbn.ts +1213 -0
- package/src/browser/platform.ts +434 -0
- package/src/browser/rng.ts +15 -0
- package/src/browser/rsa.ts +262 -0
- package/src/commands.ts +1378 -0
- package/src/company.ts +244 -0
- package/src/configuration.ts +125 -0
- package/src/endpoint.ts +350 -0
- package/src/node/index.ts +17 -0
- package/src/node/platform.ts +283 -0
- package/src/platform.ts +76 -0
- package/src/proto.d.ts +50992 -0
- package/src/proto.js +136564 -0
- package/src/restMessages.ts +311 -0
- package/src/utils.ts +169 -0
- package/src/vault.ts +844 -0
- package/src/vendorContext.ts +69 -0
- package/src/vendorModel.ts +36 -0
- package/tsconfig.json +14 -0
- package/tsconfig.rollup.json +14 -0
package/src/auth.ts
ADDED
|
@@ -0,0 +1,1514 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClientConfiguration,
|
|
3
|
+
ClientConfigurationInternal,
|
|
4
|
+
DeviceApprovalChannel,
|
|
5
|
+
DeviceVerificationMethods,
|
|
6
|
+
KeeperError,
|
|
7
|
+
LoginError,
|
|
8
|
+
TwoFactorChannelData
|
|
9
|
+
} from './configuration'
|
|
10
|
+
import {KeeperEndpoint, KeeperEnvironment} from "./endpoint";
|
|
11
|
+
import {KeyWrapper, platform} from "./platform";
|
|
12
|
+
import {AuthorizedCommand, KeeperCommand, LoginCommand, LoginResponse, LoginResponseResultCode} from "./commands";
|
|
13
|
+
import {
|
|
14
|
+
chooseErrorMessage,
|
|
15
|
+
decryptFromStorage,
|
|
16
|
+
generateEncryptionKey, wrapPassword,
|
|
17
|
+
generateUidBytes,
|
|
18
|
+
isTwoFactorResultCode,
|
|
19
|
+
normal64,
|
|
20
|
+
normal64Bytes,
|
|
21
|
+
resolvablePromise,
|
|
22
|
+
webSafe64,
|
|
23
|
+
webSafe64FromBytes
|
|
24
|
+
} from "./utils";
|
|
25
|
+
import {
|
|
26
|
+
accountSummaryMessage,
|
|
27
|
+
getEnterprisePublicKeyMessage,
|
|
28
|
+
logoutV3Message,
|
|
29
|
+
requestCreateUserMessage,
|
|
30
|
+
requestDeviceAdminApprovalMessage,
|
|
31
|
+
requestDeviceVerificationMessage,
|
|
32
|
+
RestMessage,
|
|
33
|
+
ssoServiceProviderRequestMessage,
|
|
34
|
+
startLoginMessage,
|
|
35
|
+
startLoginMessageFromSessionToken,
|
|
36
|
+
twoFactorSend2FAPushMessage,
|
|
37
|
+
twoFactorValidateMessage,
|
|
38
|
+
validateAuthHashMessage,
|
|
39
|
+
validateDeviceVerificationCodeMessage
|
|
40
|
+
} from './restMessages'
|
|
41
|
+
import {AccountSummary, Authentication} from './proto';
|
|
42
|
+
import IStartLoginRequest = Authentication.IStartLoginRequest;
|
|
43
|
+
import ITwoFactorSendPushRequest = Authentication.ITwoFactorSendPushRequest;
|
|
44
|
+
import TwoFactorExpiration = Authentication.TwoFactorExpiration;
|
|
45
|
+
import TwoFactorPushType = Authentication.TwoFactorPushType;
|
|
46
|
+
import TwoFactorChannelType = Authentication.TwoFactorChannelType;
|
|
47
|
+
import ISsoServiceProviderRequest = Authentication.ISsoServiceProviderRequest;
|
|
48
|
+
import LoginType = Authentication.LoginType;
|
|
49
|
+
import LoginMethod = Authentication.LoginMethod;
|
|
50
|
+
import IAccountSummaryElements = AccountSummary.IAccountSummaryElements;
|
|
51
|
+
|
|
52
|
+
function unifyLoginError(e: any): LoginError {
|
|
53
|
+
if (e instanceof Error) {
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(e.message);
|
|
56
|
+
} catch (jsonError) {
|
|
57
|
+
return {
|
|
58
|
+
error: "unknown",
|
|
59
|
+
message: e.message
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
return {
|
|
64
|
+
error: e.result_code,
|
|
65
|
+
message: e.result_code
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type CloseReason = {
|
|
71
|
+
code: number,
|
|
72
|
+
reason: CloseReasonMessage
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
enum CloseReasonCode {
|
|
76
|
+
CANNOT_ACCEPT = 1003,
|
|
77
|
+
NOT_CONSISTENT = 1007,
|
|
78
|
+
VIOLATED_POLICY = 1008,
|
|
79
|
+
TRY_AGAIN_LATER = 1013,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
type CloseReasonMessage = {
|
|
83
|
+
close_reason:string
|
|
84
|
+
key_id?:number
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type SocketMessage = {
|
|
88
|
+
event: 'received_totp'
|
|
89
|
+
type: 'dna'
|
|
90
|
+
passcode: string
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type SocketProxy = {
|
|
94
|
+
onOpen: (callback: () => void) => void
|
|
95
|
+
close: () => void
|
|
96
|
+
onClose: (callback: (e:Event) => void) => void
|
|
97
|
+
onError: (callback: (e: Event | Error) => void) => void
|
|
98
|
+
onMessage: (callback: (e: Uint8Array) => void) => void
|
|
99
|
+
send: (message: any) => void
|
|
100
|
+
messageQueue: any[] // Since messages are type any here, make this an any array
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class SocketListener {
|
|
104
|
+
private socket: SocketProxy | null;
|
|
105
|
+
private url: string
|
|
106
|
+
private getConnectionRequest?: (Uint8Array) => Promise<string>
|
|
107
|
+
// Listeners that receive all messages
|
|
108
|
+
private messageListeners: Array<(data: any) => void>
|
|
109
|
+
// Listeners that receive a single message
|
|
110
|
+
private singleMessageListeners: Array<{
|
|
111
|
+
resolve: (data: any) => void,
|
|
112
|
+
reject: (errorMessage: string) => void
|
|
113
|
+
}>
|
|
114
|
+
// Listeners that receive all messages
|
|
115
|
+
private closeListeners: Array<(data: any) => void>
|
|
116
|
+
// Listeners that receive a single message
|
|
117
|
+
private singleCloseListeners: Array<{
|
|
118
|
+
resolve: (data: any) => void,
|
|
119
|
+
reject: (errorMessage: string) => void
|
|
120
|
+
}>
|
|
121
|
+
// Listeners that signal a re-connected socket
|
|
122
|
+
private onOpenListeners: Array<() => void>
|
|
123
|
+
// The messageSessionUid
|
|
124
|
+
private messageSessionUid: Uint8Array
|
|
125
|
+
|
|
126
|
+
private isConnected: boolean
|
|
127
|
+
private reconnectTimeout: ReturnType<typeof setTimeout>
|
|
128
|
+
private currentBackoffSeconds: number
|
|
129
|
+
private isClosedByClient: boolean
|
|
130
|
+
|
|
131
|
+
constructor(url: string, messageSessionUid?: Uint8Array, getConnectionRequest?: (messageSessionUid:Uint8Array) => Promise<string>) {
|
|
132
|
+
console.log('Connecting to ' + url)
|
|
133
|
+
|
|
134
|
+
this.url = url
|
|
135
|
+
this.closeListeners = []
|
|
136
|
+
this.singleCloseListeners = []
|
|
137
|
+
this.messageListeners = []
|
|
138
|
+
this.singleMessageListeners = []
|
|
139
|
+
this.onOpenListeners = []
|
|
140
|
+
this.currentBackoffSeconds = SocketListener.getBaseReconnectionInterval()
|
|
141
|
+
this.isClosedByClient = false
|
|
142
|
+
this.isConnected = false
|
|
143
|
+
if (getConnectionRequest) this.getConnectionRequest = getConnectionRequest
|
|
144
|
+
|
|
145
|
+
if (messageSessionUid){
|
|
146
|
+
this.messageSessionUid = messageSessionUid
|
|
147
|
+
this.createWebsocket(this.messageSessionUid)
|
|
148
|
+
} else {
|
|
149
|
+
this.createWebsocket()
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async createWebsocket(messageSessionUid?:Uint8Array) {
|
|
154
|
+
if (this.getConnectionRequest && messageSessionUid) {
|
|
155
|
+
const connectionRequest = await this.getConnectionRequest(messageSessionUid)
|
|
156
|
+
this.socket = platform.createWebsocket(`${this.url}/${connectionRequest}`)
|
|
157
|
+
} else {
|
|
158
|
+
this.socket = platform.createWebsocket(this.url)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.socket.onOpen(() => {
|
|
162
|
+
console.log('socket opened')
|
|
163
|
+
clearTimeout(this.reconnectTimeout)
|
|
164
|
+
this.currentBackoffSeconds = SocketListener.getBaseReconnectionInterval()
|
|
165
|
+
this.handleOnOpen()
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
this.socket.onClose(async (event: Event & {reason:string, code:number}) => {
|
|
169
|
+
console.log('socket closed because: ', event)
|
|
170
|
+
|
|
171
|
+
let reason
|
|
172
|
+
this.isConnected = false
|
|
173
|
+
|
|
174
|
+
try{
|
|
175
|
+
reason = JSON.parse(event.reason)
|
|
176
|
+
} catch(error){
|
|
177
|
+
console.log('No close reason. Error message is: ', error)
|
|
178
|
+
|
|
179
|
+
if (!this.isClosedByClient) {
|
|
180
|
+
this.reconnect()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
switch (event.code){
|
|
187
|
+
case CloseReasonCode.CANNOT_ACCEPT:
|
|
188
|
+
// Exact messages that can come from CANNOT_ACCEPT:
|
|
189
|
+
// - Push server is in progress of shutting down
|
|
190
|
+
// - Push server is not registered with KA
|
|
191
|
+
// - Cannot process encrypted message.xxxx
|
|
192
|
+
|
|
193
|
+
if(reason && reason.close_reason.includes('Push server')){
|
|
194
|
+
// Tell User to try again
|
|
195
|
+
this.handleClose({code:event.code, reason})
|
|
196
|
+
} else {
|
|
197
|
+
// this would be an internal error and shouldnt reach here in production
|
|
198
|
+
console.error('Incorrect internal error: ', reason.close_reason)
|
|
199
|
+
}
|
|
200
|
+
break
|
|
201
|
+
case CloseReasonCode.NOT_CONSISTENT:
|
|
202
|
+
// Error Message: device timestamp: {time} is off by {off_time}
|
|
203
|
+
//Tell User to adjust their system clock
|
|
204
|
+
this.handleClose({ code: event.code, reason })
|
|
205
|
+
break
|
|
206
|
+
case CloseReasonCode.VIOLATED_POLICY:
|
|
207
|
+
// Error Message: duplicate messageSessionUid=${messageSessionUid}
|
|
208
|
+
// Relogin if this happens
|
|
209
|
+
this.handleClose({ code: event.code, reason })
|
|
210
|
+
break
|
|
211
|
+
case CloseReasonCode.TRY_AGAIN_LATER:
|
|
212
|
+
// Error Message: throttled messageSessionUid=${messageSessionUid}
|
|
213
|
+
//Tell User to try again in 1 minute
|
|
214
|
+
this.handleClose({ code: event.code, reason })
|
|
215
|
+
break
|
|
216
|
+
default:
|
|
217
|
+
if (!this.isClosedByClient) {
|
|
218
|
+
this.reconnect()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
this.socket.onError((e: Event | Error) => {
|
|
223
|
+
console.log('socket error: ' + e)
|
|
224
|
+
})
|
|
225
|
+
this.socket.onMessage(e => {
|
|
226
|
+
this.handleMessage(e)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
this.isConnected = true
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
registerLogin(sessionToken: string) {
|
|
233
|
+
if (!this.socket) throw new Error('Socket not available')
|
|
234
|
+
this.socket.send(sessionToken)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
onOpen(callback: () => void): void {
|
|
238
|
+
this.onOpenListeners.push(callback)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
onClose(callback: () => void): void {
|
|
242
|
+
if (!this.socket) throw new Error('Socket not available')
|
|
243
|
+
this.socket.onClose(callback)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
onError(callback: () => void): void {
|
|
247
|
+
if (!this.socket) throw new Error('Socket not available')
|
|
248
|
+
this.socket.onError(callback)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private handleOnOpen() {
|
|
252
|
+
for (let callback of this.onOpenListeners) {
|
|
253
|
+
callback()
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private handleMessage(messageData: Uint8Array): void {
|
|
258
|
+
for (let callback of this.messageListeners) {
|
|
259
|
+
callback(messageData)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
for (let {resolve} of this.singleMessageListeners) {
|
|
263
|
+
resolve(messageData)
|
|
264
|
+
}
|
|
265
|
+
this.singleMessageListeners.length = 0
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private handleClose(messageData: {code: number, reason:CloseReasonMessage}): void {
|
|
269
|
+
for (let callback of this.closeListeners) {
|
|
270
|
+
callback(messageData)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
for (let { resolve } of this.singleCloseListeners) {
|
|
274
|
+
resolve(messageData)
|
|
275
|
+
}
|
|
276
|
+
this.singleCloseListeners.length = 0
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
onPushMessage(callback: (data: any) => void): void {
|
|
280
|
+
this.messageListeners.push(callback)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
onCloseMessage(callback: (data: any) => void): void {
|
|
284
|
+
this.closeListeners.push(callback)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async getPushMessage(): Promise<any> {
|
|
288
|
+
console.log('Awaiting web socket message...')
|
|
289
|
+
return new Promise<any>((resolve, reject) => {
|
|
290
|
+
this.singleMessageListeners.push({resolve, reject})
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private static getBaseReconnectionInterval(): number {
|
|
295
|
+
return Math.random() * 5
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private reconnect() {
|
|
299
|
+
console.log(`Reconnecting websocket in ${this.currentBackoffSeconds.toFixed(2)} seconds...`)
|
|
300
|
+
|
|
301
|
+
// schedule next reconnect attempt
|
|
302
|
+
clearTimeout(this.reconnectTimeout)
|
|
303
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
304
|
+
this.createWebsocket(this.messageSessionUid)
|
|
305
|
+
}, this.currentBackoffSeconds * 1000)
|
|
306
|
+
|
|
307
|
+
this.currentBackoffSeconds = Math.min(this.currentBackoffSeconds * 2, 60) // Cap at 1 min, as suggested by docs
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
disconnect() {
|
|
311
|
+
this.isClosedByClient = true
|
|
312
|
+
this.socket = null
|
|
313
|
+
this.messageListeners.length = 0
|
|
314
|
+
|
|
315
|
+
this.currentBackoffSeconds = Math.random() * 5
|
|
316
|
+
clearTimeout(this.reconnectTimeout)
|
|
317
|
+
|
|
318
|
+
this.singleMessageListeners.length = 0
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
getIsConnected(){
|
|
322
|
+
return this.isConnected
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export function socketSendMessage(message: any, socket: WebSocket, createdSocket:any){
|
|
327
|
+
switch (socket.readyState) {
|
|
328
|
+
case 0:// CONNECTING
|
|
329
|
+
if (createdSocket.messageQueue.indexOf(message) === -1) createdSocket.messageQueue.push(message)
|
|
330
|
+
break;
|
|
331
|
+
case 1:// OPEN
|
|
332
|
+
if (createdSocket.messageQueue.indexOf(message) === -1) createdSocket.messageQueue.push(message)
|
|
333
|
+
|
|
334
|
+
if (createdSocket.messageQueue.length > 0) {
|
|
335
|
+
for (let counter = 0; counter < createdSocket.messageQueue.length; counter++) {
|
|
336
|
+
socket.send(createdSocket.messageQueue[counter])
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
createdSocket.messageQueue.length = 0
|
|
341
|
+
break;
|
|
342
|
+
case 2:// CLOSING
|
|
343
|
+
case 3:// CLOSED
|
|
344
|
+
createdSocket.messageQueue.length = 0
|
|
345
|
+
console.error('Trying to send a message while in the CLOSING or CLOSED state')
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export type LoginPayload = {
|
|
351
|
+
username: string,
|
|
352
|
+
password?: string | KeyWrapper,
|
|
353
|
+
loginToken?: Uint8Array
|
|
354
|
+
loginType?: Authentication.LoginType
|
|
355
|
+
loginMethod?: Authentication.LoginMethod,
|
|
356
|
+
v2TwoFactorToken?: string
|
|
357
|
+
resumeSessionOnly?: boolean
|
|
358
|
+
givenSessionToken?: string
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export enum UserType {
|
|
362
|
+
normal = "normal",
|
|
363
|
+
onsiteSso = "onsite_sso",
|
|
364
|
+
cloudSso = "cloud_sso"
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export type SessionParams = {
|
|
368
|
+
accountUid: Uint8Array
|
|
369
|
+
username: string
|
|
370
|
+
sessionToken: string
|
|
371
|
+
sessionTokenType: Authentication.SessionTokenType
|
|
372
|
+
dataKey: Uint8Array
|
|
373
|
+
privateKey: Uint8Array
|
|
374
|
+
eccPrivateKey?: Uint8Array
|
|
375
|
+
eccPublicKey?: Uint8Array
|
|
376
|
+
enterpriseEccPublicKey?: Uint8Array
|
|
377
|
+
clientKey: Uint8Array
|
|
378
|
+
userType: UserType
|
|
379
|
+
ssoLogoutUrl: string
|
|
380
|
+
ssoSessionId: string
|
|
381
|
+
messageSessionUid: Uint8Array
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export class Auth {
|
|
385
|
+
ssoLogoutUrl: string = ''
|
|
386
|
+
userType: UserType = UserType.normal
|
|
387
|
+
ssoSessionId: string = ''
|
|
388
|
+
dataKey: Uint8Array;
|
|
389
|
+
privateKey: Uint8Array;
|
|
390
|
+
eccPrivateKey: Uint8Array;
|
|
391
|
+
eccPublicKey: Uint8Array;
|
|
392
|
+
enterpriseEccPublicKey: Uint8Array;
|
|
393
|
+
private _accountUid: Uint8Array;
|
|
394
|
+
private _sessionToken: string = '';
|
|
395
|
+
private _sessionTokenType: Authentication.SessionTokenType | null;
|
|
396
|
+
private _username: string = '';
|
|
397
|
+
private endpoint: KeeperEndpoint;
|
|
398
|
+
private managedCompanyId?: number;
|
|
399
|
+
private messageSessionUid: Uint8Array;
|
|
400
|
+
options: ClientConfigurationInternal;
|
|
401
|
+
private socket: SocketListener | undefined;
|
|
402
|
+
public clientKey: Uint8Array;
|
|
403
|
+
private accountSummary: IAccountSummaryElements;
|
|
404
|
+
|
|
405
|
+
constructor(options: ClientConfiguration) {
|
|
406
|
+
if (options.deviceConfig && options.deviceToken) {
|
|
407
|
+
throw new Error('Both loginV2 and loginV3 token strategies supplied')
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
this.options = options as ClientConfigurationInternal
|
|
411
|
+
|
|
412
|
+
if (!this.options.deviceConfig) {
|
|
413
|
+
this.options.deviceConfig = {
|
|
414
|
+
deviceName: null,
|
|
415
|
+
deviceToken: null,
|
|
416
|
+
privateKey: null,
|
|
417
|
+
publicKey: null,
|
|
418
|
+
transmissionKeyId: null,
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (!this.options.sessionStorage) {
|
|
423
|
+
this.options.sessionStorage = {
|
|
424
|
+
lastUsername: null,
|
|
425
|
+
getCloneCode: () => null,
|
|
426
|
+
saveCloneCode: () => new Promise((res, rej) => {}),
|
|
427
|
+
getSessionParameters: () => Promise.resolve(null),
|
|
428
|
+
saveSessionParameters: () => Promise.resolve()
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
this.endpoint = new KeeperEndpoint(this.options);
|
|
433
|
+
this.endpoint.clientVersion = this.options.clientVersion || "c14.0.0";
|
|
434
|
+
this.messageSessionUid = generateUidBytes()
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
get _endpoint(): KeeperEndpoint {
|
|
438
|
+
return this.endpoint;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
get accountUid(): Uint8Array {
|
|
442
|
+
return this._accountUid;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
get clientVersion(): string {
|
|
446
|
+
return this.endpoint.clientVersion;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
get sessionToken(): string {
|
|
450
|
+
return this._sessionToken;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
get sessionTokenType(): Authentication.SessionTokenType | null {
|
|
454
|
+
return this._sessionTokenType
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
get username(): string {
|
|
458
|
+
return this._username;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
getMessageSessionUid(): Uint8Array {
|
|
462
|
+
return this.messageSessionUid;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
async idpLogout() {
|
|
466
|
+
if (this.userType == UserType.cloudSso) {
|
|
467
|
+
const payload = await this.endpoint.prepareSsoPayload(this.messageSessionUid, this.username, this.ssoSessionId)
|
|
468
|
+
|
|
469
|
+
const params = new URLSearchParams({
|
|
470
|
+
'payload': payload,
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
const url = `${this.ssoLogoutUrl}?${String(params)}`
|
|
474
|
+
|
|
475
|
+
try {
|
|
476
|
+
await this.options.authUI3.idpLogout(url);
|
|
477
|
+
} catch (e) {
|
|
478
|
+
console.log('Logout errored out: ' + e)
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
} else if (this.userType == UserType.onsiteSso) {
|
|
482
|
+
const params = new URLSearchParams({
|
|
483
|
+
'embedded': 'true',
|
|
484
|
+
'username': this.username,
|
|
485
|
+
'session_id': this.ssoSessionId,
|
|
486
|
+
'dest': 'vault'
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
const url = `${this.ssoLogoutUrl}?${String(params)}`
|
|
490
|
+
|
|
491
|
+
try {
|
|
492
|
+
await this.options.authUI3.idpLogout(url);
|
|
493
|
+
} catch (e) {
|
|
494
|
+
console.log('Logout errored out: ' + e)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
async logout() {
|
|
500
|
+
await this.executeRest(logoutV3Message())
|
|
501
|
+
await this.idpLogout()
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
connect() {
|
|
505
|
+
// When connecting to govcloud, remove the govcloud subdomain. There is no list of urls that do/don't require the govcloud subdomain, so for now do this.
|
|
506
|
+
const url = `wss://push.services.${this.options.host.replace('govcloud.', '')}/wss_open_connection`
|
|
507
|
+
const getConnectionRequest = (messageSessionUid) => this.endpoint.getPushConnectionRequest(messageSessionUid)
|
|
508
|
+
|
|
509
|
+
this.socket = new SocketListener(url, this.messageSessionUid, getConnectionRequest)
|
|
510
|
+
console.log("Socket connected")
|
|
511
|
+
this.onCloseMessage((closeReason: CloseReason) => {
|
|
512
|
+
if (this.options.onCommandFailure) {
|
|
513
|
+
this.options.onCommandFailure({
|
|
514
|
+
result_code: closeReason.code.toString(),
|
|
515
|
+
message: closeReason.reason.close_reason
|
|
516
|
+
})
|
|
517
|
+
}
|
|
518
|
+
})
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
disconnect() {
|
|
522
|
+
if (this.socket) {
|
|
523
|
+
this.socket.disconnect()
|
|
524
|
+
delete this.socket
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* useAlternate is to pass to the next function to use an alternate method, for testing a different path.
|
|
530
|
+
*/
|
|
531
|
+
async loginV3(
|
|
532
|
+
{
|
|
533
|
+
username = '',
|
|
534
|
+
password = null,
|
|
535
|
+
loginToken = null,
|
|
536
|
+
loginType = Authentication.LoginType.NORMAL,
|
|
537
|
+
loginMethod = Authentication.LoginMethod.EXISTING_ACCOUNT,
|
|
538
|
+
v2TwoFactorToken = null,
|
|
539
|
+
resumeSessionOnly = false,
|
|
540
|
+
givenSessionToken = null,
|
|
541
|
+
}: LoginPayload
|
|
542
|
+
) {
|
|
543
|
+
this._username = username || this.options.sessionStorage.lastUsername
|
|
544
|
+
|
|
545
|
+
let wrappedPassword: KeyWrapper;
|
|
546
|
+
|
|
547
|
+
if (password) {
|
|
548
|
+
if (typeof password === 'string') {
|
|
549
|
+
wrappedPassword = wrapPassword(password)
|
|
550
|
+
}
|
|
551
|
+
else
|
|
552
|
+
wrappedPassword = password
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
let needUserName: boolean
|
|
556
|
+
let isAlternate = false
|
|
557
|
+
|
|
558
|
+
const handleError = (resultCode: string, loginResponse: Authentication.ILoginResponse, error: KeeperError) => {
|
|
559
|
+
const errorMessage = chooseErrorMessage(loginResponse.loginState)
|
|
560
|
+
if (this.options.onCommandFailure) {
|
|
561
|
+
this.options.onCommandFailure({
|
|
562
|
+
result_code: resultCode,
|
|
563
|
+
message: errorMessage,
|
|
564
|
+
error: error.message,
|
|
565
|
+
})
|
|
566
|
+
} else {
|
|
567
|
+
throw error;
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
while (true) {
|
|
572
|
+
|
|
573
|
+
if (!this.options.deviceConfig.deviceToken) {
|
|
574
|
+
await this.endpoint.registerDevice()
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (!this.socket || !this.socket.getIsConnected()) {
|
|
578
|
+
this.connect()
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const startLoginRequest: IStartLoginRequest = {
|
|
582
|
+
clientVersion: this.endpoint.clientVersion,
|
|
583
|
+
encryptedDeviceToken: this.options.deviceConfig.deviceToken ?? null,
|
|
584
|
+
messageSessionUid: this.messageSessionUid,
|
|
585
|
+
loginMethod: loginMethod,
|
|
586
|
+
cloneCode: await this.options.sessionStorage.getCloneCode(this.options.host as KeeperEnvironment, this._username),
|
|
587
|
+
v2TwoFactorToken: v2TwoFactorToken
|
|
588
|
+
}
|
|
589
|
+
if (loginType !== LoginType.NORMAL && !!loginType) {
|
|
590
|
+
startLoginRequest.loginType = loginType
|
|
591
|
+
loginType = undefined
|
|
592
|
+
if (startLoginRequest.loginType == LoginType.ALTERNATE) {
|
|
593
|
+
isAlternate = true
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (loginToken) {
|
|
597
|
+
startLoginRequest.encryptedLoginToken = loginToken
|
|
598
|
+
}
|
|
599
|
+
if (needUserName || !this.options.useSessionResumption || isAlternate) {
|
|
600
|
+
startLoginRequest.username = this._username
|
|
601
|
+
needUserName = false
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
var loginResponse;
|
|
605
|
+
if (givenSessionToken){
|
|
606
|
+
this._sessionToken = givenSessionToken
|
|
607
|
+
try{
|
|
608
|
+
loginResponse = await this.executeRest(startLoginMessageFromSessionToken(startLoginRequest))
|
|
609
|
+
} catch(e){
|
|
610
|
+
if(this.options.onCommandFailure){
|
|
611
|
+
this.options.onCommandFailure({
|
|
612
|
+
result_code: 'failed_login_from_existing_session_token',
|
|
613
|
+
message: e.message,
|
|
614
|
+
})
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
} else {
|
|
618
|
+
loginResponse = await this.executeRest(startLoginMessage(startLoginRequest))
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (loginResponse.cloneCode && loginResponse.cloneCode.length > 0) {
|
|
622
|
+
this.options.sessionStorage.saveCloneCode(this.options.host as KeeperEnvironment, this._username, loginResponse.cloneCode)
|
|
623
|
+
}
|
|
624
|
+
if (resumeSessionOnly && loginResponse && (loginResponse.loginState != Authentication.LoginState.LOGGED_IN)) {
|
|
625
|
+
return {
|
|
626
|
+
result: 'notLoggedin'
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
console.log(loginResponse)
|
|
630
|
+
console.log("login state =", loginResponse.loginState);
|
|
631
|
+
|
|
632
|
+
switch (loginResponse.loginState) {
|
|
633
|
+
case Authentication.LoginState.ACCOUNT_LOCKED:
|
|
634
|
+
case Authentication.LoginState.INVALID_LOGINSTATE:
|
|
635
|
+
case Authentication.LoginState.LOGGED_OUT:
|
|
636
|
+
case Authentication.LoginState.AFTER_CLOUD_SSO_LOGIN:
|
|
637
|
+
case Authentication.LoginState.LOGIN_TOKEN_EXPIRED:
|
|
638
|
+
case Authentication.LoginState.DEVICE_ACCOUNT_LOCKED:
|
|
639
|
+
case Authentication.LoginState.DEVICE_LOCKED:
|
|
640
|
+
handleError('generic_error', loginResponse, new Error(`Unable to login, login state = ${loginResponse.loginState}`))
|
|
641
|
+
return
|
|
642
|
+
case Authentication.LoginState.REQUIRES_ACCOUNT_CREATION:
|
|
643
|
+
if (this.userType === UserType.cloudSso) {
|
|
644
|
+
await this.createSsoUser(loginResponse.encryptedLoginToken)
|
|
645
|
+
} else {
|
|
646
|
+
await this.createUser(this._username, wrappedPassword)
|
|
647
|
+
}
|
|
648
|
+
break;
|
|
649
|
+
case Authentication.LoginState.UPGRADE:
|
|
650
|
+
handleError('generic_error', loginResponse, new Error(`Unable to login, login state = ${loginResponse.loginState}`))
|
|
651
|
+
return;
|
|
652
|
+
case Authentication.LoginState.REQUIRES_USERNAME:
|
|
653
|
+
if (!this._username) {
|
|
654
|
+
handleError('generic_error', loginResponse, new Error(`No username supplied, login state = ${loginResponse.loginState}`));
|
|
655
|
+
return
|
|
656
|
+
}
|
|
657
|
+
needUserName = true
|
|
658
|
+
break;
|
|
659
|
+
case Authentication.LoginState.DEVICE_APPROVAL_REQUIRED:
|
|
660
|
+
case Authentication.LoginState.REQUIRES_DEVICE_ENCRYPTED_DATA_KEY:
|
|
661
|
+
if (!loginResponse.encryptedLoginToken) {
|
|
662
|
+
throw new Error('Login token missing from API response')
|
|
663
|
+
}
|
|
664
|
+
if (givenSessionToken) return { result: 'notLoggedin' }
|
|
665
|
+
try {
|
|
666
|
+
loginToken = await this.verifyDevice(username, loginResponse.encryptedLoginToken, loginResponse.loginState == Authentication.LoginState.REQUIRES_DEVICE_ENCRYPTED_DATA_KEY)
|
|
667
|
+
} catch (e) {
|
|
668
|
+
handleError('auth_failed', loginResponse, e)
|
|
669
|
+
return
|
|
670
|
+
}
|
|
671
|
+
break;
|
|
672
|
+
case Authentication.LoginState.LICENSE_EXPIRED:
|
|
673
|
+
handleError('license_expired', loginResponse, new Error(loginResponse.message))
|
|
674
|
+
return;
|
|
675
|
+
case Authentication.LoginState.REGION_REDIRECT:
|
|
676
|
+
// TODO: put region_redirect in its own loop since
|
|
677
|
+
// its unique to the other states.
|
|
678
|
+
this.options.host = loginResponse.stateSpecificValue
|
|
679
|
+
loginToken = undefined
|
|
680
|
+
if (this.options.onRegionChanged) {
|
|
681
|
+
this.options.onRegionChanged(loginResponse.stateSpecificValue)
|
|
682
|
+
}
|
|
683
|
+
// Current socket no longer pointing to the right region
|
|
684
|
+
this.disconnect()
|
|
685
|
+
break;
|
|
686
|
+
case Authentication.LoginState.REDIRECT_CLOUD_SSO:
|
|
687
|
+
console.log("Cloud SSO Connect login");
|
|
688
|
+
if (!loginResponse.url) {
|
|
689
|
+
throw new Error('URL missing from API response')
|
|
690
|
+
}
|
|
691
|
+
this.ssoLogoutUrl = loginResponse.url.replace('login', 'logout')
|
|
692
|
+
this.userType = UserType.cloudSso
|
|
693
|
+
let payload = await this._endpoint.prepareSsoPayload(this.messageSessionUid)
|
|
694
|
+
let cloudSsoLoginUrl = loginResponse.url + "?payload=" + payload;
|
|
695
|
+
if (this.options.authUI3.redirectCallback) {
|
|
696
|
+
this.options.authUI3.redirectCallback(cloudSsoLoginUrl)
|
|
697
|
+
return
|
|
698
|
+
} else if (this.options.authUI3.ssoLogin) {
|
|
699
|
+
const token = await this.options.authUI3.ssoLogin(cloudSsoLoginUrl)
|
|
700
|
+
const cloudResp = await this.endpoint.decryptCloudSsoResponse(token)
|
|
701
|
+
console.log(cloudResp)
|
|
702
|
+
this._username = cloudResp.email
|
|
703
|
+
loginToken = cloudResp.encryptedLoginToken
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
case Authentication.LoginState.REDIRECT_ONSITE_SSO:
|
|
707
|
+
console.log("SSO Connect login");
|
|
708
|
+
if (!loginResponse.url) {
|
|
709
|
+
throw new Error('URL missing from API response')
|
|
710
|
+
}
|
|
711
|
+
this.ssoLogoutUrl = loginResponse.url.replace('login', 'logout')
|
|
712
|
+
this.userType = UserType.onsiteSso
|
|
713
|
+
|
|
714
|
+
let onsitePublicKey = await this._endpoint.getOnsitePublicKey()
|
|
715
|
+
let onsiteSsoLoginUrl = loginResponse.url + '?embedded&key=' + onsitePublicKey
|
|
716
|
+
|
|
717
|
+
if (this.options.authUI3.redirectCallback) {
|
|
718
|
+
this.options.authUI3.redirectCallback(onsiteSsoLoginUrl)
|
|
719
|
+
return
|
|
720
|
+
} else if (this.options.authUI3.ssoLogin) {
|
|
721
|
+
const onsiteResp = await this.options.authUI3.ssoLogin(onsiteSsoLoginUrl)
|
|
722
|
+
console.log(onsiteResp)
|
|
723
|
+
this._username = onsiteResp.email
|
|
724
|
+
wrappedPassword = wrapPassword(onsiteResp.password)
|
|
725
|
+
loginType = LoginType.SSO
|
|
726
|
+
loginMethod = LoginMethod.AFTER_SSO
|
|
727
|
+
break;
|
|
728
|
+
}
|
|
729
|
+
case Authentication.LoginState.REQUIRES_2FA:
|
|
730
|
+
try{
|
|
731
|
+
loginToken = await this.handleTwoFactor(loginResponse)
|
|
732
|
+
} catch(e){
|
|
733
|
+
if (e?.message && e.message == 'push_declined'){
|
|
734
|
+
handleError(e.message, loginResponse, e)
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
break
|
|
738
|
+
|
|
739
|
+
case Authentication.LoginState.REQUIRES_AUTH_HASH:
|
|
740
|
+
// TODO: loop in authHashLogin until successful or get into
|
|
741
|
+
// some other state other than Authentication.LoginState.REQUIRES_AUTH_HASH
|
|
742
|
+
if (!wrappedPassword && this.options.authUI3?.getPassword) {
|
|
743
|
+
password = await this.options.authUI3.getPassword()
|
|
744
|
+
if (password) {
|
|
745
|
+
if (typeof password === 'string') {
|
|
746
|
+
wrappedPassword = wrapPassword(password)
|
|
747
|
+
}
|
|
748
|
+
else
|
|
749
|
+
wrappedPassword = password
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (!wrappedPassword) {
|
|
753
|
+
throw new Error('User password required and not provided')
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
try {
|
|
757
|
+
await this.authHashLogin(loginResponse, username, wrappedPassword, isAlternate)
|
|
758
|
+
return;
|
|
759
|
+
} catch (e) {
|
|
760
|
+
wrappedPassword = null
|
|
761
|
+
handleError('auth_failed', loginResponse, e)
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
case Authentication.LoginState.LOGGED_IN:
|
|
765
|
+
try {
|
|
766
|
+
await this.loginSuccess(loginResponse, null)
|
|
767
|
+
console.log("Exiting on loginState = LOGGED_IN");
|
|
768
|
+
return;
|
|
769
|
+
} catch (e) {
|
|
770
|
+
console.log('Error in Authentication.LoginState.LOGGED_IN: ', e)
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* The MV3 browser extension runs in a service worker that shuts down every 5 minutes.
|
|
779
|
+
* This rehydrates the Auth class and re-opens our socket with the session parameters.
|
|
780
|
+
*/
|
|
781
|
+
async continueSession() {
|
|
782
|
+
if (!this.options.sessionStorage) {
|
|
783
|
+
throw new Error('Missing configuration option to get session parameters')
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
const sessionParams = await this.options.sessionStorage.getSessionParameters()
|
|
787
|
+
if (!sessionParams) {
|
|
788
|
+
throw new Error('No session to resume')
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
this.messageSessionUid = sessionParams.messageSessionUid
|
|
792
|
+
this._username = sessionParams.username
|
|
793
|
+
this.dataKey = sessionParams.dataKey
|
|
794
|
+
this.clientKey = sessionParams.clientKey
|
|
795
|
+
this.privateKey = sessionParams.privateKey
|
|
796
|
+
this.eccPrivateKey = sessionParams.eccPrivateKey
|
|
797
|
+
this.eccPublicKey = sessionParams.eccPublicKey
|
|
798
|
+
this.enterpriseEccPublicKey = sessionParams.enterpriseEccPublicKey
|
|
799
|
+
this.ssoLogoutUrl = sessionParams.ssoLogoutUrl
|
|
800
|
+
this.ssoSessionId = sessionParams.ssoSessionId
|
|
801
|
+
this.userType = sessionParams.userType
|
|
802
|
+
|
|
803
|
+
if (!this.socket || !this.socket.getIsConnected()) {
|
|
804
|
+
this.connect()
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
this.setLoginParameters(sessionParams.sessionToken, sessionParams.sessionTokenType, sessionParams.accountUid)
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
private getSessionParameters(): SessionParams {
|
|
811
|
+
return {
|
|
812
|
+
accountUid: this._accountUid,
|
|
813
|
+
username: this._username,
|
|
814
|
+
sessionToken: this._sessionToken,
|
|
815
|
+
sessionTokenType: this._sessionTokenType,
|
|
816
|
+
dataKey: this.dataKey,
|
|
817
|
+
privateKey: this.privateKey,
|
|
818
|
+
eccPrivateKey: this.eccPrivateKey,
|
|
819
|
+
eccPublicKey: this.eccPublicKey,
|
|
820
|
+
enterpriseEccPublicKey: this.enterpriseEccPublicKey,
|
|
821
|
+
clientKey: this.clientKey,
|
|
822
|
+
userType: this.userType,
|
|
823
|
+
ssoLogoutUrl: this.ssoLogoutUrl,
|
|
824
|
+
ssoSessionId: this.ssoSessionId,
|
|
825
|
+
messageSessionUid: this.messageSessionUid
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
async getSsoProvider(ssoDomain: string, locale?: string) {
|
|
830
|
+
let domainRequest: ISsoServiceProviderRequest = {
|
|
831
|
+
name: ssoDomain.trim(),
|
|
832
|
+
locale: locale,
|
|
833
|
+
clientVersion: this.endpoint.clientVersion,
|
|
834
|
+
}
|
|
835
|
+
const domainResponse = await this.executeRest(ssoServiceProviderRequestMessage(domainRequest))
|
|
836
|
+
const params = domainResponse.isCloud
|
|
837
|
+
? '?payload=' + await this._endpoint.prepareSsoPayload(this.messageSessionUid)
|
|
838
|
+
: '?embedded&key=' + await this._endpoint.getOnsitePublicKey()
|
|
839
|
+
|
|
840
|
+
this.userType = domainResponse.isCloud ? UserType.cloudSso : UserType.onsiteSso
|
|
841
|
+
this.ssoLogoutUrl = domainResponse.spUrl.replace('login', 'logout')
|
|
842
|
+
|
|
843
|
+
return {
|
|
844
|
+
url: domainResponse.spUrl + params,
|
|
845
|
+
name: domainResponse.name,
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
verifyDevice(username: string, loginToken: Uint8Array, isCloud: boolean = false): Promise<Uint8Array> {
|
|
850
|
+
return new Promise<Uint8Array>((resolve, reject) => {
|
|
851
|
+
if (!this.options.authUI3) {
|
|
852
|
+
reject(new Error('No authUI3 provided. authUI3 required to verify devices'))
|
|
853
|
+
return
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
let emailSent = false
|
|
857
|
+
let tfaExpiration = TwoFactorExpiration.TWO_FA_EXP_IMMEDIATELY
|
|
858
|
+
const deviceConfig = this.options.deviceConfig
|
|
859
|
+
let channels: DeviceApprovalChannel[]
|
|
860
|
+
if (!isCloud) {
|
|
861
|
+
channels = [
|
|
862
|
+
{
|
|
863
|
+
channel: DeviceVerificationMethods.Email,
|
|
864
|
+
sendApprovalRequest: async () => {
|
|
865
|
+
await this.executeRest(requestDeviceVerificationMessage({
|
|
866
|
+
username: username,
|
|
867
|
+
verificationChannel: emailSent ? 'email_resend' : 'email',
|
|
868
|
+
encryptedDeviceToken: deviceConfig.deviceToken,
|
|
869
|
+
clientVersion: this.endpoint.clientVersion,
|
|
870
|
+
messageSessionUid: this.messageSessionUid
|
|
871
|
+
}))
|
|
872
|
+
emailSent = true
|
|
873
|
+
},
|
|
874
|
+
validateCode: async (code) => {
|
|
875
|
+
await this.executeRest(validateDeviceVerificationCodeMessage({
|
|
876
|
+
verificationCode: code,
|
|
877
|
+
username: username,
|
|
878
|
+
}))
|
|
879
|
+
resumeWithToken(loginToken)
|
|
880
|
+
}
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
channel: DeviceVerificationMethods.KeeperPush,
|
|
884
|
+
sendApprovalRequest: async () => {
|
|
885
|
+
await this.executeRest(twoFactorSend2FAPushMessage({
|
|
886
|
+
encryptedLoginToken: loginToken,
|
|
887
|
+
pushType: TwoFactorPushType.TWO_FA_PUSH_KEEPER
|
|
888
|
+
}))
|
|
889
|
+
}
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
channel: DeviceVerificationMethods.TFA,
|
|
893
|
+
sendApprovalRequest: async () => {
|
|
894
|
+
await this.executeRest(twoFactorSend2FAPushMessage({
|
|
895
|
+
encryptedLoginToken: loginToken,
|
|
896
|
+
}))
|
|
897
|
+
},
|
|
898
|
+
validateCode: async (code) => {
|
|
899
|
+
const twoFactorValidateMsg = twoFactorValidateMessage({
|
|
900
|
+
encryptedLoginToken: loginToken,
|
|
901
|
+
value: code,
|
|
902
|
+
expireIn: tfaExpiration
|
|
903
|
+
})
|
|
904
|
+
const twoFactorValidateResp = await this.executeRest(twoFactorValidateMsg)
|
|
905
|
+
if (twoFactorValidateResp.encryptedLoginToken) {
|
|
906
|
+
const wssRs: Record<string, any> = {
|
|
907
|
+
event: 'received_totp',
|
|
908
|
+
encryptedLoginToken: platform.bytesToBase64(twoFactorValidateResp.encryptedLoginToken)
|
|
909
|
+
}
|
|
910
|
+
processPushNotification(wssRs)
|
|
911
|
+
}
|
|
912
|
+
},
|
|
913
|
+
setExpiration: expiration => {
|
|
914
|
+
tfaExpiration = expiration
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
];
|
|
918
|
+
} else {
|
|
919
|
+
channels = [
|
|
920
|
+
{
|
|
921
|
+
channel: DeviceVerificationMethods.KeeperPush,
|
|
922
|
+
sendApprovalRequest: async () => {
|
|
923
|
+
await this.executeRest(twoFactorSend2FAPushMessage({
|
|
924
|
+
encryptedLoginToken: loginToken,
|
|
925
|
+
pushType: TwoFactorPushType.TWO_FA_PUSH_KEEPER
|
|
926
|
+
}))
|
|
927
|
+
}
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
channel: DeviceVerificationMethods.AdminApproval,
|
|
931
|
+
sendApprovalRequest: async () => {
|
|
932
|
+
await this.executeRest(requestDeviceAdminApprovalMessage({
|
|
933
|
+
username: username,
|
|
934
|
+
verificationChannel: emailSent ? 'email_resend' : 'email',
|
|
935
|
+
encryptedDeviceToken: deviceConfig.deviceToken,
|
|
936
|
+
clientVersion: this.endpoint.clientVersion,
|
|
937
|
+
messageSessionUid: this.messageSessionUid
|
|
938
|
+
}))
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
]
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
let done = false
|
|
945
|
+
const resumeWithToken = (token: Uint8Array) => {
|
|
946
|
+
done = true
|
|
947
|
+
resolve(token)
|
|
948
|
+
}
|
|
949
|
+
const rejectWithError = (error: Error) => {
|
|
950
|
+
done = true
|
|
951
|
+
reject(error)
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const processPushNotification = (wssRs: Record<string, any>) => {
|
|
955
|
+
if (wssRs.event === 'received_totp') {
|
|
956
|
+
const token = wssRs.encryptedLoginToken ? normal64Bytes(wssRs.encryptedLoginToken) : loginToken
|
|
957
|
+
resumeWithToken(token)
|
|
958
|
+
} else if (wssRs.message === 'device_approved') {
|
|
959
|
+
if (wssRs.approved) {
|
|
960
|
+
resumeWithToken(loginToken)
|
|
961
|
+
} else {
|
|
962
|
+
rejectWithError(new Error('Rejected'))
|
|
963
|
+
}
|
|
964
|
+
} else if (wssRs.command === 'device_verified') {
|
|
965
|
+
if (this.options.onDeviceVerified) {
|
|
966
|
+
this.options.onDeviceVerified(true)
|
|
967
|
+
}
|
|
968
|
+
resumeWithToken(loginToken)
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// response from the client true - try again, false - cancel
|
|
973
|
+
this.options.authUI3.waitForDeviceApproval(channels, isCloud)
|
|
974
|
+
.then((ok) => {
|
|
975
|
+
if (ok) {
|
|
976
|
+
resumeWithToken(loginToken)
|
|
977
|
+
} else {
|
|
978
|
+
rejectWithError(new Error('Canceled'))
|
|
979
|
+
}
|
|
980
|
+
})
|
|
981
|
+
.catch(reason => rejectWithError(reason))
|
|
982
|
+
|
|
983
|
+
// receive push notification
|
|
984
|
+
;(async () => {
|
|
985
|
+
while (!done) {
|
|
986
|
+
const pushMessage = await this.socket.getPushMessage()
|
|
987
|
+
const wssClientResponse = await this.endpoint.decryptPushMessage(pushMessage)
|
|
988
|
+
if (!done) {
|
|
989
|
+
const wssRs = JSON.parse(wssClientResponse.message)
|
|
990
|
+
console.log(wssRs)
|
|
991
|
+
processPushNotification(wssRs)
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
})();
|
|
995
|
+
})
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
private handleTwoFactor(loginResponse: Authentication.ILoginResponse): Promise<Uint8Array> {
|
|
999
|
+
return new Promise<Uint8Array>((resolve, reject) => {
|
|
1000
|
+
if (!loginResponse.channels) {
|
|
1001
|
+
reject(new Error('Channels not provided by API'))
|
|
1002
|
+
return
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
const loginToken = loginResponse.encryptedLoginToken
|
|
1006
|
+
|
|
1007
|
+
let done = false
|
|
1008
|
+
let twoFactorWaitCancel = resolvablePromise();
|
|
1009
|
+
const resumeWithToken = (token: Uint8Array) => {
|
|
1010
|
+
done = true
|
|
1011
|
+
twoFactorWaitCancel.resolve()
|
|
1012
|
+
resolve(token)
|
|
1013
|
+
}
|
|
1014
|
+
const rejectWithError = (error: Error) => {
|
|
1015
|
+
done = true
|
|
1016
|
+
twoFactorWaitCancel.resolve()
|
|
1017
|
+
reject(error)
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
let tfaExpiration = TwoFactorExpiration.TWO_FA_EXP_IMMEDIATELY
|
|
1021
|
+
const submitCode = async (channel: Authentication.TwoFactorChannelType, code: string) => {
|
|
1022
|
+
const channelInfo = loginResponse.channels.find(x => x.channelType === channel)
|
|
1023
|
+
let valueType: Authentication.TwoFactorValueType | undefined
|
|
1024
|
+
switch (channelInfo.channelType) {
|
|
1025
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_DNA:
|
|
1026
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_CODE_DNA
|
|
1027
|
+
break
|
|
1028
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_DUO:
|
|
1029
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_CODE_DUO
|
|
1030
|
+
break
|
|
1031
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_SMS:
|
|
1032
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_CODE_SMS
|
|
1033
|
+
break
|
|
1034
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_TOTP:
|
|
1035
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_CODE_TOTP
|
|
1036
|
+
break
|
|
1037
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_RSA:
|
|
1038
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_CODE_RSA
|
|
1039
|
+
break
|
|
1040
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_U2F:
|
|
1041
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_RESP_U2F
|
|
1042
|
+
break
|
|
1043
|
+
case Authentication.TwoFactorChannelType.TWO_FA_CT_WEBAUTHN:
|
|
1044
|
+
valueType = Authentication.TwoFactorValueType.TWO_FA_RESP_WEBAUTHN
|
|
1045
|
+
break
|
|
1046
|
+
default:
|
|
1047
|
+
valueType = undefined
|
|
1048
|
+
break
|
|
1049
|
+
}
|
|
1050
|
+
const twoFactorValidateMsg = twoFactorValidateMessage({
|
|
1051
|
+
channelUid: channelInfo ? channelInfo.channelUid : undefined,
|
|
1052
|
+
encryptedLoginToken: loginToken,
|
|
1053
|
+
value: code,
|
|
1054
|
+
expireIn: tfaExpiration,
|
|
1055
|
+
valueType: valueType,
|
|
1056
|
+
})
|
|
1057
|
+
const twoFactorValidateResp = await this.executeRest(twoFactorValidateMsg)
|
|
1058
|
+
if (twoFactorValidateResp.encryptedLoginToken) {
|
|
1059
|
+
resumeWithToken(twoFactorValidateResp.encryptedLoginToken)
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
let lastPushChannel = TwoFactorChannelType.TWO_FA_CT_NONE
|
|
1064
|
+
const submitPush = async (channel: TwoFactorChannelType, pushType: TwoFactorPushType) => {
|
|
1065
|
+
const sendPushRequest: ITwoFactorSendPushRequest = {
|
|
1066
|
+
encryptedLoginToken: loginResponse.encryptedLoginToken,
|
|
1067
|
+
pushType: pushType,
|
|
1068
|
+
expireIn: tfaExpiration
|
|
1069
|
+
}
|
|
1070
|
+
await this.executeRest(twoFactorSend2FAPushMessage(sendPushRequest))
|
|
1071
|
+
lastPushChannel = channel
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
const channels: TwoFactorChannelData[] = loginResponse.channels
|
|
1075
|
+
.map((ch) => {
|
|
1076
|
+
const tfachannelData: TwoFactorChannelData = {
|
|
1077
|
+
channel: ch,
|
|
1078
|
+
setExpiration: (exp) => {
|
|
1079
|
+
tfaExpiration = exp
|
|
1080
|
+
},
|
|
1081
|
+
sendCode: async (code) => {
|
|
1082
|
+
await submitCode(ch.channelType, code)
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
switch (ch.channelType) {
|
|
1086
|
+
case TwoFactorChannelType.TWO_FA_CT_U2F:
|
|
1087
|
+
case TwoFactorChannelType.TWO_FA_CT_WEBAUTHN:
|
|
1088
|
+
// add support for security key as push
|
|
1089
|
+
break;
|
|
1090
|
+
case TwoFactorChannelType.TWO_FA_CT_TOTP:
|
|
1091
|
+
case TwoFactorChannelType.TWO_FA_CT_RSA:
|
|
1092
|
+
break
|
|
1093
|
+
case TwoFactorChannelType.TWO_FA_CT_SMS:
|
|
1094
|
+
tfachannelData.availablePushes = [TwoFactorPushType.TWO_FA_PUSH_SMS]
|
|
1095
|
+
break
|
|
1096
|
+
case TwoFactorChannelType.TWO_FA_CT_DNA:
|
|
1097
|
+
tfachannelData.availablePushes = [TwoFactorPushType.TWO_FA_PUSH_DNA]
|
|
1098
|
+
break
|
|
1099
|
+
case TwoFactorChannelType.TWO_FA_CT_KEEPER:
|
|
1100
|
+
case TwoFactorChannelType.TWO_FA_CT_DUO:
|
|
1101
|
+
if (ch.capabilities) {
|
|
1102
|
+
tfachannelData.availablePushes = ch.capabilities
|
|
1103
|
+
.map(cap => {
|
|
1104
|
+
switch (cap) {
|
|
1105
|
+
case 'push':
|
|
1106
|
+
return TwoFactorPushType.TWO_FA_PUSH_DUO_PUSH
|
|
1107
|
+
case 'sms':
|
|
1108
|
+
return TwoFactorPushType.TWO_FA_PUSH_DUO_TEXT
|
|
1109
|
+
case 'phone':
|
|
1110
|
+
return TwoFactorPushType.TWO_FA_PUSH_DUO_CALL
|
|
1111
|
+
default:
|
|
1112
|
+
return undefined
|
|
1113
|
+
}
|
|
1114
|
+
}).filter(cap => !!cap).map(cap => cap!)
|
|
1115
|
+
}
|
|
1116
|
+
break
|
|
1117
|
+
}
|
|
1118
|
+
if (tfachannelData.availablePushes) {
|
|
1119
|
+
tfachannelData.sendPush = async (pushType: TwoFactorPushType) => {
|
|
1120
|
+
submitPush(ch.channelType, pushType)
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return tfachannelData
|
|
1124
|
+
}).filter((chd: TwoFactorChannelData | undefined) => !!chd).map(chd => chd!)
|
|
1125
|
+
|
|
1126
|
+
const processPushNotification = (wssRs: Record<string, any>) => {
|
|
1127
|
+
if (wssRs.event === 'received_totp') {
|
|
1128
|
+
if (wssRs.encryptedLoginToken) {
|
|
1129
|
+
const token = normal64Bytes(wssRs.encryptedLoginToken)
|
|
1130
|
+
resumeWithToken(token)
|
|
1131
|
+
} else if (wssRs.passcode) {
|
|
1132
|
+
(async () => {
|
|
1133
|
+
await submitCode(lastPushChannel, wssRs.passcode)
|
|
1134
|
+
})()
|
|
1135
|
+
} else {
|
|
1136
|
+
rejectWithError(new Error('push_declined'))
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
this.options.authUI3.waitForTwoFactorCode(channels, twoFactorWaitCancel.promise)
|
|
1142
|
+
.then(ok => {
|
|
1143
|
+
if (ok) {
|
|
1144
|
+
resumeWithToken(loginToken)
|
|
1145
|
+
} else {
|
|
1146
|
+
rejectWithError(new Error('Canceled'))
|
|
1147
|
+
}
|
|
1148
|
+
})
|
|
1149
|
+
.catch(reason => rejectWithError(reason))
|
|
1150
|
+
|
|
1151
|
+
// receive push notification
|
|
1152
|
+
;(async () => {
|
|
1153
|
+
while (!done) {
|
|
1154
|
+
const pushMessage = await this.socket.getPushMessage()
|
|
1155
|
+
const wssClientResponse = await this.endpoint.decryptPushMessage(pushMessage)
|
|
1156
|
+
if (!done) {
|
|
1157
|
+
const wssRs = JSON.parse(wssClientResponse.message)
|
|
1158
|
+
console.log(wssRs)
|
|
1159
|
+
processPushNotification(wssRs)
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
})();
|
|
1163
|
+
})
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
async authHashLogin(loginResponse: Authentication.ILoginResponse, username: string, password: KeyWrapper, useAlternate: boolean = false) {
|
|
1167
|
+
// TODO test for account transfer and account recovery
|
|
1168
|
+
if (!loginResponse.salt) {
|
|
1169
|
+
throw new Error('Salt missing from API response')
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
const salt = useAlternate ? loginResponse.salt.find(s => s.name === 'alternate') : loginResponse.salt[0]
|
|
1173
|
+
if (!salt.salt || !salt.iterations) {
|
|
1174
|
+
throw new Error('Salt missing from API response')
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
this.options.salt = salt.salt
|
|
1178
|
+
this.options.iterations = salt.iterations
|
|
1179
|
+
|
|
1180
|
+
const authHashKey = await platform.deriveKey(password, salt.salt, salt.iterations);
|
|
1181
|
+
let authHash = await platform.calcAuthVerifier(authHashKey);
|
|
1182
|
+
|
|
1183
|
+
const loginMsg = validateAuthHashMessage({
|
|
1184
|
+
authResponse: authHash,
|
|
1185
|
+
encryptedLoginToken: loginResponse.encryptedLoginToken
|
|
1186
|
+
})
|
|
1187
|
+
const loginResp = await this.executeRest(loginMsg)
|
|
1188
|
+
console.log(loginResp)
|
|
1189
|
+
if (loginResp.cloneCode && loginResp.cloneCode.length > 0) {
|
|
1190
|
+
this.options.sessionStorage.saveCloneCode(this.options.host as KeeperEnvironment, this._username, loginResp.cloneCode)
|
|
1191
|
+
}
|
|
1192
|
+
await this.loginSuccess(loginResp, password, salt)
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
async loginSuccess(loginResponse: Authentication.ILoginResponse, password: KeyWrapper, salt: Authentication.ISalt | undefined = undefined) {
|
|
1196
|
+
this._username = loginResponse.primaryUsername || this._username
|
|
1197
|
+
if (!loginResponse.encryptedSessionToken || !loginResponse.encryptedDataKey || !loginResponse.accountUid) {
|
|
1198
|
+
return
|
|
1199
|
+
}
|
|
1200
|
+
this.setLoginParameters(webSafe64FromBytes(loginResponse.encryptedSessionToken), loginResponse.sessionTokenType, loginResponse.accountUid)
|
|
1201
|
+
switch (loginResponse.encryptedDataKeyType) {
|
|
1202
|
+
case Authentication.EncryptedDataKeyType.BY_DEVICE_PUBLIC_KEY:
|
|
1203
|
+
this.dataKey = await platform.privateDecryptEC(loginResponse.encryptedDataKey, this.options.deviceConfig.privateKey, this.options.deviceConfig.publicKey)
|
|
1204
|
+
break;
|
|
1205
|
+
case Authentication.EncryptedDataKeyType.BY_PASSWORD:
|
|
1206
|
+
this.dataKey = await decryptEncryptionParams(password, loginResponse.encryptedDataKey);
|
|
1207
|
+
break;
|
|
1208
|
+
case Authentication.EncryptedDataKeyType.BY_ALTERNATE:
|
|
1209
|
+
if (salt) {
|
|
1210
|
+
const encKey = await platform.deriveKeyV2('data_key', password, salt.salt, salt.iterations)
|
|
1211
|
+
this.dataKey = await platform.aesGcmDecrypt(loginResponse.encryptedDataKey, encKey)
|
|
1212
|
+
}
|
|
1213
|
+
break;
|
|
1214
|
+
case Authentication.EncryptedDataKeyType.NO_KEY:
|
|
1215
|
+
case Authentication.EncryptedDataKeyType.BY_BIO:
|
|
1216
|
+
throw new Error(`Data Key type ${loginResponse.encryptedDataKeyType} decryption not implemented`)
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
await this.loadAccountSummary()
|
|
1220
|
+
|
|
1221
|
+
let encryptedPrivateKey: Uint8Array
|
|
1222
|
+
let encryptedEccPrivateKey: Uint8Array
|
|
1223
|
+
if (this.options.kvs) {
|
|
1224
|
+
const encryptedPrivateKeyString = this.options.kvs.getValue(`${this._username}/private_key`)
|
|
1225
|
+
if (encryptedPrivateKeyString) {
|
|
1226
|
+
encryptedPrivateKey = platform.base64ToBytes(encryptedPrivateKeyString)
|
|
1227
|
+
}
|
|
1228
|
+
const encryptedEccPrivateKeyString = this.options.kvs.getValue(`${this._username}/ecc_private_key`)
|
|
1229
|
+
if (encryptedEccPrivateKey) {
|
|
1230
|
+
encryptedEccPrivateKey = platform.base64ToBytes(encryptedEccPrivateKeyString)
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
if (!encryptedPrivateKey || !encryptedEccPrivateKey) {
|
|
1234
|
+
encryptedPrivateKey = this.accountSummary.keysInfo.encryptedPrivateKey
|
|
1235
|
+
encryptedEccPrivateKey = this.accountSummary.keysInfo.encryptedEccPrivateKey
|
|
1236
|
+
if (this.options.kvs) {
|
|
1237
|
+
this.options.kvs.saveValue(`${this._username}/private_key`, platform.bytesToBase64(encryptedPrivateKey))
|
|
1238
|
+
if (encryptedEccPrivateKey) {
|
|
1239
|
+
this.options.kvs.saveValue(`${this._username}/ecc_private_key`, platform.bytesToBase64(encryptedEccPrivateKey))
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
this.privateKey = await platform.aesCbcDecrypt(encryptedPrivateKey, this.dataKey, true)
|
|
1244
|
+
|
|
1245
|
+
if (encryptedEccPrivateKey?.length) {
|
|
1246
|
+
this.eccPrivateKey = await platform.aesGcmDecrypt(encryptedEccPrivateKey, this.dataKey)
|
|
1247
|
+
this.eccPublicKey = this.accountSummary.keysInfo.eccPublicKey
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
this.clientKey = await platform.aesCbcDecrypt(this.accountSummary.clientKey, this.dataKey, true)
|
|
1251
|
+
|
|
1252
|
+
if (this.options.sessionStorage) {
|
|
1253
|
+
this.options.sessionStorage.saveSessionParameters(this.getSessionParameters())
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
async loadAccountSummary() {
|
|
1258
|
+
this.accountSummary = await this.executeRest(accountSummaryMessage({
|
|
1259
|
+
summaryVersion: 1
|
|
1260
|
+
}));
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
async login(username: string, password: KeyWrapper) {
|
|
1264
|
+
try {
|
|
1265
|
+
let preLoginResponse = await this.endpoint.getPreLogin(username);
|
|
1266
|
+
if (!preLoginResponse.salt) {
|
|
1267
|
+
throw new Error('Salt missing from API response')
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
let salt = preLoginResponse.salt[0];
|
|
1271
|
+
if (!salt.salt || !salt.iterations) {
|
|
1272
|
+
throw new Error('Salt missing from API response')
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
let authHashKey = await platform.deriveKey(password, salt.salt, salt.iterations);
|
|
1276
|
+
let authHash = platform.bytesToBase64(await platform.calcAuthVerifier(authHashKey));
|
|
1277
|
+
|
|
1278
|
+
let loginCommand = new LoginCommand();
|
|
1279
|
+
loginCommand.command = "login";
|
|
1280
|
+
loginCommand.username = username;
|
|
1281
|
+
loginCommand.version = 2;
|
|
1282
|
+
loginCommand.auth_response = webSafe64(authHash);
|
|
1283
|
+
loginCommand.platform_device_token = webSafe64FromBytes(this.endpoint.deviceToken);
|
|
1284
|
+
loginCommand.include = ["keys"]; //["license","settings","group","sync_log","keys","enforcements","client_key","images","is_enterprise_admin","security_keys"]
|
|
1285
|
+
if (this.managedCompanyId) {
|
|
1286
|
+
loginCommand.enterprise_id = this.managedCompanyId
|
|
1287
|
+
}
|
|
1288
|
+
let loginResponse: LoginResponse;
|
|
1289
|
+
let socketListener: SocketListener | null = null;
|
|
1290
|
+
while (true) {
|
|
1291
|
+
loginResponse = await this.endpoint.executeV2Command<LoginResponse>(loginCommand);
|
|
1292
|
+
if (loginResponse.result_code === "auth_success")
|
|
1293
|
+
break;
|
|
1294
|
+
console.log(loginResponse)
|
|
1295
|
+
if (isTwoFactorResultCode(loginResponse.result_code)) {
|
|
1296
|
+
if (!!loginResponse.u2f_challenge) {
|
|
1297
|
+
loginResponse.u2f_challenge = JSON.parse(loginResponse.u2f_challenge as string);
|
|
1298
|
+
}
|
|
1299
|
+
if (!this.options.authUI)
|
|
1300
|
+
break;
|
|
1301
|
+
let errorMessage = loginResponse.result_code === LoginResponseResultCode.InvalidTOTP
|
|
1302
|
+
? loginResponse.message
|
|
1303
|
+
: undefined;
|
|
1304
|
+
if (loginResponse.channel === 'two_factor_channel_duo' && loginResponse.url) {
|
|
1305
|
+
loginCommand['2fa_mode'] = 'push'
|
|
1306
|
+
socketListener = new SocketListener(loginResponse.url)
|
|
1307
|
+
} else {
|
|
1308
|
+
let token: string
|
|
1309
|
+
if (socketListener) {
|
|
1310
|
+
const pushMessage: SocketMessage = JSON.parse(await socketListener.getPushMessage())
|
|
1311
|
+
socketListener.disconnect()
|
|
1312
|
+
console.log(pushMessage)
|
|
1313
|
+
token = pushMessage.passcode
|
|
1314
|
+
} else {
|
|
1315
|
+
token = await this.options.authUI.getTwoFactorCode(errorMessage)
|
|
1316
|
+
}
|
|
1317
|
+
if (!token)
|
|
1318
|
+
break;
|
|
1319
|
+
loginCommand["2fa_token"] = token;
|
|
1320
|
+
}
|
|
1321
|
+
loginCommand['2fa_type'] = 'one_time';
|
|
1322
|
+
loginCommand["device_token_expire_days"] = 9999;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
this._sessionToken = loginResponse.session_token;
|
|
1326
|
+
this._username = username;
|
|
1327
|
+
this.dataKey = await decryptEncryptionParamsString(password, loginResponse.keys.encryption_params);
|
|
1328
|
+
if (loginResponse.keys.encrypted_private_key) {
|
|
1329
|
+
this.privateKey = await decryptFromStorage(loginResponse.keys.encrypted_private_key, this.dataKey);
|
|
1330
|
+
}
|
|
1331
|
+
} catch (e) {
|
|
1332
|
+
throw unifyLoginError(e);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
async managedCompanyLogin(username: string, password: KeyWrapper, companyId: number) {
|
|
1337
|
+
this.managedCompanyId = companyId;
|
|
1338
|
+
await this.login(username, password);
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
async executeCommand<Command extends KeeperCommand>(command: Command): Promise<Command["response"]> {
|
|
1342
|
+
if (!command.username) {
|
|
1343
|
+
command.username = this._username;
|
|
1344
|
+
}
|
|
1345
|
+
if (command instanceof AuthorizedCommand) {
|
|
1346
|
+
command.device_id = "JS Keeper API";
|
|
1347
|
+
command.session_token = this._sessionToken;
|
|
1348
|
+
}
|
|
1349
|
+
return this.endpoint.executeV2Command(command);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
async executeRest<TIn, TOut>(message: RestMessage<TIn, TOut>): Promise<TOut> {
|
|
1353
|
+
return this.endpoint.executeRest(message, this._sessionToken);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
async get(path: string) {
|
|
1357
|
+
return this.endpoint.get(path)
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
setLoginParameters(sessionToken: string, sessionTokenType: Authentication.SessionTokenType, accountUid: Uint8Array) {
|
|
1361
|
+
this._sessionToken = sessionToken;
|
|
1362
|
+
this._sessionTokenType = sessionTokenType
|
|
1363
|
+
this._accountUid = accountUid;
|
|
1364
|
+
if (!this.socket) {
|
|
1365
|
+
throw new Error('No socket available')
|
|
1366
|
+
}
|
|
1367
|
+
if (this.socket.getIsConnected()) {
|
|
1368
|
+
this.socket.registerLogin(this._sessionToken)
|
|
1369
|
+
}
|
|
1370
|
+
this.socket.onOpen(() => {
|
|
1371
|
+
this.socket.registerLogin(this._sessionToken)
|
|
1372
|
+
})
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
async registerDevice() {
|
|
1376
|
+
await this.endpoint.registerDevice()
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
onClose(callback: () => void): void {
|
|
1380
|
+
if (!this.socket) {
|
|
1381
|
+
throw new Error('No socket available')
|
|
1382
|
+
}
|
|
1383
|
+
this.socket.onClose(callback)
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
onError(callback: () => void): void {
|
|
1387
|
+
if (!this.socket) {
|
|
1388
|
+
throw new Error('No socket available')
|
|
1389
|
+
}
|
|
1390
|
+
this.socket.onError(callback)
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
onPushMessage(callback: (data: any) => void): void {
|
|
1394
|
+
if (!this.socket) {
|
|
1395
|
+
throw new Error('No socket available')
|
|
1396
|
+
}
|
|
1397
|
+
this.socket.onPushMessage(callback)
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
onCloseMessage(callback: (data:any) => void): void {
|
|
1401
|
+
if (!this.socket) {
|
|
1402
|
+
throw new Error('No socket available')
|
|
1403
|
+
}
|
|
1404
|
+
this.socket.onCloseMessage(callback)
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
async getPushMessage(): Promise<any> {
|
|
1408
|
+
if (!this.socket) {
|
|
1409
|
+
throw new Error('No socket available')
|
|
1410
|
+
}
|
|
1411
|
+
const pushMessage = await this.socket.getPushMessage()
|
|
1412
|
+
const wssClientResponse = await this.endpoint.decryptPushMessage(pushMessage)
|
|
1413
|
+
console.log(wssClientResponse.message)
|
|
1414
|
+
return JSON.parse(wssClientResponse.message)
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
private async createUserRequest(dataKey: Uint8Array): Promise<Authentication.ICreateUserRequest> {
|
|
1418
|
+
const rsaKeys = await platform.generateRSAKeyPair()
|
|
1419
|
+
const rsaEncryptedPrivateKey = await platform.aesCbcEncrypt(rsaKeys.privateKey, dataKey, true)
|
|
1420
|
+
|
|
1421
|
+
const ecKeys = await platform.generateECKeyPair()
|
|
1422
|
+
const eccEncryptedPrivateKey = await platform.aesGcmEncrypt(ecKeys.privateKey, dataKey)
|
|
1423
|
+
|
|
1424
|
+
const encryptedClientKey = await platform.aesCbcEncrypt(generateEncryptionKey(), dataKey, true)
|
|
1425
|
+
|
|
1426
|
+
return {
|
|
1427
|
+
rsaPublicKey: rsaKeys.publicKey,
|
|
1428
|
+
rsaEncryptedPrivateKey: rsaEncryptedPrivateKey,
|
|
1429
|
+
eccPublicKey: ecKeys.publicKey,
|
|
1430
|
+
eccEncryptedPrivateKey: eccEncryptedPrivateKey,
|
|
1431
|
+
encryptedDeviceToken: this.options.deviceConfig.deviceToken,
|
|
1432
|
+
encryptedClientKey: encryptedClientKey,
|
|
1433
|
+
clientVersion: this.options.clientVersion,
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
public async createUser(username: string, password: KeyWrapper) {
|
|
1438
|
+
const iterations = 100000
|
|
1439
|
+
const dataKey = generateEncryptionKey()
|
|
1440
|
+
const authVerifier = await createAuthVerifier(password, iterations)
|
|
1441
|
+
const encryptionParams = await createEncryptionParams(password, dataKey, iterations)
|
|
1442
|
+
const request = await this.createUserRequest(dataKey)
|
|
1443
|
+
const regUserMsg = requestCreateUserMessage({
|
|
1444
|
+
...request,
|
|
1445
|
+
username: username,
|
|
1446
|
+
authVerifier: authVerifier,
|
|
1447
|
+
encryptionParams: encryptionParams,
|
|
1448
|
+
}, false)
|
|
1449
|
+
await this.executeRest(regUserMsg)
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
private async createSsoUser(loginToken: Uint8Array) {
|
|
1453
|
+
const dataKey = generateEncryptionKey()
|
|
1454
|
+
const encryptedDeviceDataKey = await platform.publicEncryptEC(dataKey, this.options.deviceConfig.publicKey)
|
|
1455
|
+
const request = await this.createUserRequest(dataKey)
|
|
1456
|
+
const regUserMsg = requestCreateUserMessage({
|
|
1457
|
+
...request,
|
|
1458
|
+
username: this._username,
|
|
1459
|
+
encryptedLoginToken: loginToken,
|
|
1460
|
+
encryptedDeviceDataKey: encryptedDeviceDataKey
|
|
1461
|
+
}, true)
|
|
1462
|
+
await this.executeRest(regUserMsg)
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
public async getEnterpriseECCPublicKey() {
|
|
1466
|
+
const resp = await this.executeRest(getEnterprisePublicKeyMessage())
|
|
1467
|
+
if (resp.enterpriseECCPublicKey) {
|
|
1468
|
+
this.enterpriseEccPublicKey = resp.enterpriseECCPublicKey
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
const iterationsToBytes = (iterations: number): Uint8Array => {
|
|
1474
|
+
const iterationBytes = new ArrayBuffer(4)
|
|
1475
|
+
new DataView(iterationBytes).setUint32(0, iterations)
|
|
1476
|
+
const bytes = new Uint8Array(iterationBytes)
|
|
1477
|
+
bytes[0] = 1 // version
|
|
1478
|
+
return bytes
|
|
1479
|
+
};
|
|
1480
|
+
|
|
1481
|
+
export async function createAuthVerifier(password: KeyWrapper, iterations: number): Promise<Uint8Array> {
|
|
1482
|
+
const salt = platform.getRandomBytes(16);
|
|
1483
|
+
const authHashKey = await platform.deriveKey(password, salt, iterations);
|
|
1484
|
+
return Uint8Array.of(...iterationsToBytes(iterations), ...salt, ...authHashKey)
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
export async function createEncryptionParams(password: KeyWrapper, dataKey: Uint8Array, iterations: number): Promise<Uint8Array> {
|
|
1488
|
+
const salt = platform.getRandomBytes(16);
|
|
1489
|
+
const authHashKey = await platform.deriveKey(password, salt, iterations);
|
|
1490
|
+
const doubledDataKey = Uint8Array.of(...dataKey, ...dataKey)
|
|
1491
|
+
const encryptedDoubledKey = await platform.aesCbcEncrypt(doubledDataKey, authHashKey, false)
|
|
1492
|
+
return Uint8Array.of(...iterationsToBytes(iterations), ...salt, ...encryptedDoubledKey)
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
async function decryptEncryptionParamsString(password: KeyWrapper, encryptionParams: string): Promise<Uint8Array> {
|
|
1496
|
+
return decryptEncryptionParams(password, platform.base64ToBytes(normal64(encryptionParams)))
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
export async function decryptEncryptionParams(password: KeyWrapper, encryptionParams: Uint8Array): Promise<Uint8Array> {
|
|
1500
|
+
let corruptedEncryptionParametersMessage = "Corrupted encryption parameters";
|
|
1501
|
+
if (encryptionParams[0] !== 1)
|
|
1502
|
+
throw new Error(corruptedEncryptionParametersMessage);
|
|
1503
|
+
let iterations = (encryptionParams[1] << 16) + (encryptionParams[2] << 8) + encryptionParams[3];
|
|
1504
|
+
let saltBytes = encryptionParams.subarray(4, 20);
|
|
1505
|
+
let masterKey = await platform.deriveKey(password, saltBytes, iterations);
|
|
1506
|
+
let encryptedDoubledDataKey = encryptionParams.subarray(20);
|
|
1507
|
+
let doubledDataKey = await platform.aesCbcDecrypt(encryptedDoubledDataKey, masterKey, false);
|
|
1508
|
+
for (let i = 0; i < 32; i++) {
|
|
1509
|
+
if (doubledDataKey[i] !== doubledDataKey[i + 32]) {
|
|
1510
|
+
throw new Error(corruptedEncryptionParametersMessage);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
return doubledDataKey.slice(0, 32);
|
|
1514
|
+
}
|