@keeper-security/keeperapi 16.0.1 → 16.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/07113f92cc3a9f5dc57b92f54542a63463f1fa9a +1 -0
  2. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/1ba6467ba06d4bfc0c8581f4ee12c2c0f687214e +1 -0
  3. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/1de1e40928c5c58c4f677d93986cdff01b3d0417 +1 -0
  4. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/47382883a57ad5790d3fd6abd39f33f773726b3b +1 -0
  5. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/4939a895ecf4daac58b0d73bccd49876515d41b8 +1 -0
  6. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/592d89407340c5ec6ad006df327e588b3f442eca +1 -0
  7. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/59783c8cc0cc9d984f5407c218d213bca4c98503 +1 -0
  8. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/61fa6cf725249a1cae9b94b74a8c23aa3efd2ca1 +1 -0
  9. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/77aced5528ce05fe900fdf7634042ec3c0f18255 +1 -0
  10. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/b32ea8d6d3de0c6d8e178eff069fea4e11fa92b1 +1 -0
  11. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/c05be8364ff56aba0298689783666ddb97a31285 +1 -0
  12. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/e23bf49223ba8b7ec926e46c40b27b0353cfc50e +1 -0
  13. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/code/cache/eec92c105b2694c31bff21903ddc3ef81af8f056 +1 -0
  14. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/07113f92cc3a9f5dc57b92f54542a63463f1fa9a +1 -0
  15. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/1ba6467ba06d4bfc0c8581f4ee12c2c0f687214e +1 -0
  16. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/1de1e40928c5c58c4f677d93986cdff01b3d0417 +1 -0
  17. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/47382883a57ad5790d3fd6abd39f33f773726b3b +1 -0
  18. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/4939a895ecf4daac58b0d73bccd49876515d41b8 +1 -0
  19. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/592d89407340c5ec6ad006df327e588b3f442eca +1 -0
  20. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/59783c8cc0cc9d984f5407c218d213bca4c98503 +1 -0
  21. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/61fa6cf725249a1cae9b94b74a8c23aa3efd2ca1 +1 -0
  22. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/77aced5528ce05fe900fdf7634042ec3c0f18255 +1 -0
  23. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/b32ea8d6d3de0c6d8e178eff069fea4e11fa92b1 +1 -0
  24. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/c05be8364ff56aba0298689783666ddb97a31285 +1 -0
  25. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/e23bf49223ba8b7ec926e46c40b27b0353cfc50e +1 -0
  26. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/semanticDiagnostics/cache/eec92c105b2694c31bff21903ddc3ef81af8f056 +1 -0
  27. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/07113f92cc3a9f5dc57b92f54542a63463f1fa9a +1 -0
  28. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/1ba6467ba06d4bfc0c8581f4ee12c2c0f687214e +1 -0
  29. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/1de1e40928c5c58c4f677d93986cdff01b3d0417 +1 -0
  30. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/47382883a57ad5790d3fd6abd39f33f773726b3b +1 -0
  31. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/4939a895ecf4daac58b0d73bccd49876515d41b8 +1 -0
  32. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/592d89407340c5ec6ad006df327e588b3f442eca +1 -0
  33. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/59783c8cc0cc9d984f5407c218d213bca4c98503 +1 -0
  34. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/61fa6cf725249a1cae9b94b74a8c23aa3efd2ca1 +1 -0
  35. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/77aced5528ce05fe900fdf7634042ec3c0f18255 +1 -0
  36. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/b32ea8d6d3de0c6d8e178eff069fea4e11fa92b1 +1 -0
  37. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/c05be8364ff56aba0298689783666ddb97a31285 +1 -0
  38. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/e23bf49223ba8b7ec926e46c40b27b0353cfc50e +1 -0
  39. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/syntacticDiagnostics/cache/eec92c105b2694c31bff21903ddc3ef81af8f056 +1 -0
  40. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/20b49cde4def23063b280689e4ff4d5a3803712b +0 -0
  41. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/3809196a67de680945038f2b4846e2e3b4af35aa +0 -0
  42. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/4ad5d47b1ce7bf45cc7d9ff8c970e1fc57f446f3 +0 -0
  43. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/5a0816a3c916ff0e4961dc0ec2da48646f2ac5aa +0 -0
  44. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/6182f5491d41e8f10acfbcf46ee875587904f5a3 +0 -0
  45. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/7ca2e31bcece668dfa5de5e1349ba34a757b5140 +0 -0
  46. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/86a4b0102f5568ac0a5b946d05c55f42c30b472d +0 -0
  47. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/87fae47dd5b05377c04cfe377699d748414dc1c9 +0 -0
  48. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/a7c23ecebcaf23c9346007731c5796b96c580738 +0 -0
  49. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/ac4d101c3489192db3e0ec98430a2336cba9a741 +0 -0
  50. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/b1eb441c5b806d06ba6bb36fcfd0cc4746c23a8a +0 -0
  51. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/b7942903000069a51e317fef1595a8ea1d8b828d +0 -0
  52. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/cee91236390168fd38b01aaae7bed3099bb4555a +0 -0
  53. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/d7c87ce194d923e6f02c7e570008e88ade1cbabf +0 -0
  54. package/.rpt2_cache/rpt2_73ef004c41e5fb714e8076cf96455df4f040d49c/types/cache/fba70878178c036fb4e9e1f19bdb465a1270d258 +0 -0
  55. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/05d17f791979143cbce20e3e3e811aa19ed8b492 +1 -0
  56. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/07113f92cc3a9f5dc57b92f54542a63463f1fa9a +1 -0
  57. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/1ba6467ba06d4bfc0c8581f4ee12c2c0f687214e +1 -0
  58. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/1de1e40928c5c58c4f677d93986cdff01b3d0417 +1 -0
  59. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/47382883a57ad5790d3fd6abd39f33f773726b3b +1 -0
  60. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/4d58c1113d07816b1909aaef4395fd8b4d0ee13c +1 -0
  61. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/4ee978699d6de2a60214b16c42d87f8e9309636b +1 -0
  62. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/50f4a014d14ada987c125e6ea55d4e6e75605313 +1 -0
  63. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/58aa8c228c99b690d3ca1f3b464585c41d1cd4bb +1 -0
  64. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/592d89407340c5ec6ad006df327e588b3f442eca +1 -0
  65. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/59783c8cc0cc9d984f5407c218d213bca4c98503 +1 -0
  66. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/61fa6cf725249a1cae9b94b74a8c23aa3efd2ca1 +1 -0
  67. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/89f8a81d9d078b69f9fa7fa95251b38ccc394a3b +1 -0
  68. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/b32ea8d6d3de0c6d8e178eff069fea4e11fa92b1 +1 -0
  69. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/c05be8364ff56aba0298689783666ddb97a31285 +1 -0
  70. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/e23bf49223ba8b7ec926e46c40b27b0353cfc50e +1 -0
  71. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/code/cache/eec92c105b2694c31bff21903ddc3ef81af8f056 +1 -0
  72. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/05d17f791979143cbce20e3e3e811aa19ed8b492 +1 -0
  73. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/07113f92cc3a9f5dc57b92f54542a63463f1fa9a +1 -0
  74. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/1ba6467ba06d4bfc0c8581f4ee12c2c0f687214e +1 -0
  75. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/1de1e40928c5c58c4f677d93986cdff01b3d0417 +1 -0
  76. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/47382883a57ad5790d3fd6abd39f33f773726b3b +1 -0
  77. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/4d58c1113d07816b1909aaef4395fd8b4d0ee13c +1 -0
  78. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/4ee978699d6de2a60214b16c42d87f8e9309636b +1 -0
  79. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/50f4a014d14ada987c125e6ea55d4e6e75605313 +1 -0
  80. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/58aa8c228c99b690d3ca1f3b464585c41d1cd4bb +1 -0
  81. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/592d89407340c5ec6ad006df327e588b3f442eca +1 -0
  82. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/59783c8cc0cc9d984f5407c218d213bca4c98503 +1 -0
  83. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/61fa6cf725249a1cae9b94b74a8c23aa3efd2ca1 +1 -0
  84. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/89f8a81d9d078b69f9fa7fa95251b38ccc394a3b +1 -0
  85. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/b32ea8d6d3de0c6d8e178eff069fea4e11fa92b1 +1 -0
  86. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/c05be8364ff56aba0298689783666ddb97a31285 +1 -0
  87. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/e23bf49223ba8b7ec926e46c40b27b0353cfc50e +1 -0
  88. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/semanticDiagnostics/cache/eec92c105b2694c31bff21903ddc3ef81af8f056 +1 -0
  89. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/05d17f791979143cbce20e3e3e811aa19ed8b492 +1 -0
  90. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/07113f92cc3a9f5dc57b92f54542a63463f1fa9a +1 -0
  91. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/1ba6467ba06d4bfc0c8581f4ee12c2c0f687214e +1 -0
  92. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/1de1e40928c5c58c4f677d93986cdff01b3d0417 +1 -0
  93. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/47382883a57ad5790d3fd6abd39f33f773726b3b +1 -0
  94. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/4d58c1113d07816b1909aaef4395fd8b4d0ee13c +1 -0
  95. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/4ee978699d6de2a60214b16c42d87f8e9309636b +1 -0
  96. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/50f4a014d14ada987c125e6ea55d4e6e75605313 +1 -0
  97. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/58aa8c228c99b690d3ca1f3b464585c41d1cd4bb +1 -0
  98. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/592d89407340c5ec6ad006df327e588b3f442eca +1 -0
  99. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/59783c8cc0cc9d984f5407c218d213bca4c98503 +1 -0
  100. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/61fa6cf725249a1cae9b94b74a8c23aa3efd2ca1 +1 -0
  101. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/89f8a81d9d078b69f9fa7fa95251b38ccc394a3b +1 -0
  102. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/b32ea8d6d3de0c6d8e178eff069fea4e11fa92b1 +1 -0
  103. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/c05be8364ff56aba0298689783666ddb97a31285 +1 -0
  104. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/e23bf49223ba8b7ec926e46c40b27b0353cfc50e +1 -0
  105. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/syntacticDiagnostics/cache/eec92c105b2694c31bff21903ddc3ef81af8f056 +1 -0
  106. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/20b49cde4def23063b280689e4ff4d5a3803712b +0 -0
  107. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/3809196a67de680945038f2b4846e2e3b4af35aa +0 -0
  108. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/4ad5d47b1ce7bf45cc7d9ff8c970e1fc57f446f3 +0 -0
  109. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/5a0816a3c916ff0e4961dc0ec2da48646f2ac5aa +0 -0
  110. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/6182f5491d41e8f10acfbcf46ee875587904f5a3 +0 -0
  111. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/7ca2e31bcece668dfa5de5e1349ba34a757b5140 +0 -0
  112. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/86a4b0102f5568ac0a5b946d05c55f42c30b472d +0 -0
  113. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/87fae47dd5b05377c04cfe377699d748414dc1c9 +0 -0
  114. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/a7c23ecebcaf23c9346007731c5796b96c580738 +0 -0
  115. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/ac4d101c3489192db3e0ec98430a2336cba9a741 +0 -0
  116. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/b1eb441c5b806d06ba6bb36fcfd0cc4746c23a8a +0 -0
  117. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/b7942903000069a51e317fef1595a8ea1d8b828d +0 -0
  118. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/cee91236390168fd38b01aaae7bed3099bb4555a +0 -0
  119. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/d7c87ce194d923e6f02c7e570008e88ade1cbabf +0 -0
  120. package/.rpt2_cache/rpt2_e52dc086a65136b8064433446ffcd05307935b95/types/cache/fba70878178c036fb4e9e1f19bdb465a1270d258 +0 -0
  121. package/babel.config.js +6 -0
  122. package/package.json +7 -10
  123. package/rollup.config.js +50 -0
  124. package/scripts/cleanDistFolder.js +9 -0
  125. package/src/__tests__/utils.test.js +13 -0
  126. package/src/auth.ts +1514 -0
  127. package/src/browser/asn1hex.ts +296 -0
  128. package/src/browser/index.ts +17 -0
  129. package/src/browser/jsbn.ts +1213 -0
  130. package/src/browser/platform.ts +434 -0
  131. package/src/browser/rng.ts +15 -0
  132. package/src/browser/rsa.ts +262 -0
  133. package/src/commands.ts +1378 -0
  134. package/src/company.ts +244 -0
  135. package/src/configuration.ts +125 -0
  136. package/src/endpoint.ts +350 -0
  137. package/src/node/index.ts +17 -0
  138. package/src/node/platform.ts +283 -0
  139. package/src/platform.ts +76 -0
  140. package/{dist → src}/proto.d.ts +0 -0
  141. package/src/proto.js +136564 -0
  142. package/src/restMessages.ts +311 -0
  143. package/src/utils.ts +169 -0
  144. package/src/vault.ts +844 -0
  145. package/src/vendorContext.ts +69 -0
  146. package/src/vendorModel.ts +36 -0
  147. package/tsconfig.json +14 -0
  148. 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
+ }