@lifeready/core 0.6.0-beta.1

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 (225) hide show
  1. package/README.md +62 -0
  2. package/bundles/lifeready-core.umd.js +15939 -0
  3. package/bundles/lifeready-core.umd.js.map +1 -0
  4. package/bundles/lifeready-core.umd.min.js +2 -0
  5. package/bundles/lifeready-core.umd.min.js.map +1 -0
  6. package/esm2015/lib/_common/ast.js +40 -0
  7. package/esm2015/lib/_common/deferred-promise.js +24 -0
  8. package/esm2015/lib/_common/exceptions.js +157 -0
  9. package/esm2015/lib/_common/queries.gql.js +190 -0
  10. package/esm2015/lib/_common/run-outside-angular.js +79 -0
  11. package/esm2015/lib/_common/types.js +1 -0
  12. package/esm2015/lib/_common/utils.js +44 -0
  13. package/esm2015/lib/api/contact-card.gql.js +79 -0
  14. package/esm2015/lib/api/contact-card.service.js +154 -0
  15. package/esm2015/lib/api/contact-card2.gql.js +60 -0
  16. package/esm2015/lib/api/contact-card2.service.js +103 -0
  17. package/esm2015/lib/api/file.service.js +74 -0
  18. package/esm2015/lib/api/item2.gql.js +110 -0
  19. package/esm2015/lib/api/item2.service.js +311 -0
  20. package/esm2015/lib/api/key-exchange.gql.js +188 -0
  21. package/esm2015/lib/api/key-exchange.service.js +442 -0
  22. package/esm2015/lib/api/key-exchange.types.js +18 -0
  23. package/esm2015/lib/api/key-exchange2.gql.js +171 -0
  24. package/esm2015/lib/api/key-exchange2.service.js +479 -0
  25. package/esm2015/lib/api/lock.gql.js +40 -0
  26. package/esm2015/lib/api/lock.service.js +64 -0
  27. package/esm2015/lib/api/lr-apollo.service.js +46 -0
  28. package/esm2015/lib/api/lr-graphql/index.js +6 -0
  29. package/esm2015/lib/api/lr-graphql/lr-graphql.service.js +155 -0
  30. package/esm2015/lib/api/lr-graphql/lr-merged-mutation.js +213 -0
  31. package/esm2015/lib/api/lr-graphql/lr-mutation-base.js +51 -0
  32. package/esm2015/lib/api/lr-graphql/lr-mutation.js +48 -0
  33. package/esm2015/lib/api/lr-graphql/lr.service.js +18 -0
  34. package/esm2015/lib/api/message.service.js +138 -0
  35. package/esm2015/lib/api/persist.service.js +181 -0
  36. package/esm2015/lib/api/query-processor/common-processors.service.js +93 -0
  37. package/esm2015/lib/api/query-processor/index.js +3 -0
  38. package/esm2015/lib/api/query-processor/query-processor.service.js +192 -0
  39. package/esm2015/lib/api/query-processor/tp-password-reset-processor.service.js +109 -0
  40. package/esm2015/lib/api/shared-contact-card.service.js +119 -0
  41. package/esm2015/lib/api/shared-contact-card2.gql.js +41 -0
  42. package/esm2015/lib/api/shared-contact-card2.service.js +117 -0
  43. package/esm2015/lib/api/time.service.js +146 -0
  44. package/esm2015/lib/api/types/graphql.types.js +7 -0
  45. package/esm2015/lib/api/types/index.js +3 -0
  46. package/esm2015/lib/api/types/lr-graphql.types.js +71 -0
  47. package/esm2015/lib/auth/auth.config.js +57 -0
  48. package/esm2015/lib/auth/auth.gql.js +48 -0
  49. package/esm2015/lib/auth/auth.types.js +27 -0
  50. package/esm2015/lib/auth/idle.service.js +168 -0
  51. package/esm2015/lib/auth/idle.types.js +7 -0
  52. package/esm2015/lib/auth/lbop.service.js +355 -0
  53. package/esm2015/lib/auth/life-ready-auth.service.js +333 -0
  54. package/esm2015/lib/auth/password.service.js +320 -0
  55. package/esm2015/lib/auth/register.service.js +172 -0
  56. package/esm2015/lib/auth/two-factor.service.js +74 -0
  57. package/esm2015/lib/category/category-meta.service.js +99 -0
  58. package/esm2015/lib/category/category.gql.js +406 -0
  59. package/esm2015/lib/category/category.service.js +390 -0
  60. package/esm2015/lib/category/category.types.js +29 -0
  61. package/esm2015/lib/cryptography/cryptography.types.js +11 -0
  62. package/esm2015/lib/cryptography/encryption.service.js +189 -0
  63. package/esm2015/lib/cryptography/key-factory.service.js +237 -0
  64. package/esm2015/lib/cryptography/key-graph.service.js +280 -0
  65. package/esm2015/lib/cryptography/key-meta.service.js +200 -0
  66. package/esm2015/lib/cryptography/key.service.js +124 -0
  67. package/esm2015/lib/cryptography/slip39.service.js +169 -0
  68. package/esm2015/lib/cryptography/web-crypto.service.js +29 -0
  69. package/esm2015/lib/life-ready.config.js +84 -0
  70. package/esm2015/lib/life-ready.module.js +74 -0
  71. package/esm2015/lib/plan/plan.gql.js +123 -0
  72. package/esm2015/lib/plan/plan.service.js +149 -0
  73. package/esm2015/lib/plan/plan.types.js +11 -0
  74. package/esm2015/lib/record/record-attachment.service.js +101 -0
  75. package/esm2015/lib/record/record.gql.js +179 -0
  76. package/esm2015/lib/record/record.service.js +206 -0
  77. package/esm2015/lib/record/record.types.js +15 -0
  78. package/esm2015/lib/record-type/record-type.service.js +75 -0
  79. package/esm2015/lib/record-type/record-type.types.js +28 -0
  80. package/esm2015/lib/scenario/approvals/scenario-approval.gql.js +105 -0
  81. package/esm2015/lib/scenario/approvals/scenario-approval.types.js +1 -0
  82. package/esm2015/lib/scenario/approvals/scenario-approver.service.js +300 -0
  83. package/esm2015/lib/scenario/claimants/scenario-claimant.gql.js +52 -0
  84. package/esm2015/lib/scenario/claimants/scenario-claimant.service.js +97 -0
  85. package/esm2015/lib/scenario/claimants/scenario-claimant.types.js +1 -0
  86. package/esm2015/lib/scenario/receivers/scenario-receiver.gql.js +150 -0
  87. package/esm2015/lib/scenario/receivers/scenario-receiver.service.js +229 -0
  88. package/esm2015/lib/scenario/receivers/scenario-receiver.types.js +1 -0
  89. package/esm2015/lib/scenario/scenario-setup.service.js +269 -0
  90. package/esm2015/lib/scenario/scenario.gql.js +368 -0
  91. package/esm2015/lib/scenario/scenario.service.js +611 -0
  92. package/esm2015/lib/scenario/scenario.types.js +64 -0
  93. package/esm2015/lib/search/search.gql.js +62 -0
  94. package/esm2015/lib/search/search.service.js +156 -0
  95. package/esm2015/lib/search/search.types.js +6 -0
  96. package/esm2015/lib/trusted-parties/tp-password-reset-request.service.js +112 -0
  97. package/esm2015/lib/trusted-parties/tp-password-reset-user.service.js +266 -0
  98. package/esm2015/lib/trusted-parties/tp-password-reset.gql.js +232 -0
  99. package/esm2015/lib/trusted-parties/tp-password-reset.service.js +300 -0
  100. package/esm2015/lib/trusted-parties/trusted-party.gql.js +148 -0
  101. package/esm2015/lib/trusted-parties/trusted-party.service.js +326 -0
  102. package/esm2015/lib/trusted-parties/trusted-party.types.js +41 -0
  103. package/esm2015/lib/trusted-parties/trusted-party2.gql.js +87 -0
  104. package/esm2015/lib/trusted-parties/trusted-party2.service.js +215 -0
  105. package/esm2015/lib/users/profile-details.service.js +214 -0
  106. package/esm2015/lib/users/profile.gql.js +97 -0
  107. package/esm2015/lib/users/profile.service.js +169 -0
  108. package/esm2015/lib/users/profile.types.js +34 -0
  109. package/esm2015/lib/users/user.gql.js +60 -0
  110. package/esm2015/lib/users/user.service.js +79 -0
  111. package/esm2015/lib/users/user.types.js +5 -0
  112. package/esm2015/lifeready-core.js +10 -0
  113. package/esm2015/public-api.js +81 -0
  114. package/fesm2015/lifeready-core.js +13290 -0
  115. package/fesm2015/lifeready-core.js.map +1 -0
  116. package/lib/_common/ast.d.ts +11 -0
  117. package/lib/_common/deferred-promise.d.ts +12 -0
  118. package/lib/_common/exceptions.d.ts +109 -0
  119. package/lib/_common/queries.gql.d.ts +10 -0
  120. package/lib/_common/run-outside-angular.d.ts +14 -0
  121. package/lib/_common/types.d.ts +10 -0
  122. package/lib/_common/utils.d.ts +3 -0
  123. package/lib/api/contact-card.gql.d.ts +7 -0
  124. package/lib/api/contact-card.service.d.ts +52 -0
  125. package/lib/api/contact-card2.gql.d.ts +34 -0
  126. package/lib/api/contact-card2.service.d.ts +49 -0
  127. package/lib/api/file.service.d.ts +18 -0
  128. package/lib/api/item2.gql.d.ts +96 -0
  129. package/lib/api/item2.service.d.ts +177 -0
  130. package/lib/api/key-exchange.gql.d.ts +9 -0
  131. package/lib/api/key-exchange.service.d.ts +39 -0
  132. package/lib/api/key-exchange.types.d.ts +196 -0
  133. package/lib/api/key-exchange2.gql.d.ts +125 -0
  134. package/lib/api/key-exchange2.service.d.ts +187 -0
  135. package/lib/api/lock.gql.d.ts +27 -0
  136. package/lib/api/lock.service.d.ts +25 -0
  137. package/lib/api/lr-apollo.service.d.ts +15 -0
  138. package/lib/api/lr-graphql/index.d.ts +5 -0
  139. package/lib/api/lr-graphql/lr-graphql.service.d.ts +60 -0
  140. package/lib/api/lr-graphql/lr-merged-mutation.d.ts +27 -0
  141. package/lib/api/lr-graphql/lr-mutation-base.d.ts +28 -0
  142. package/lib/api/lr-graphql/lr-mutation.d.ts +8 -0
  143. package/lib/api/lr-graphql/lr.service.d.ts +9 -0
  144. package/lib/api/message.service.d.ts +58 -0
  145. package/lib/api/persist.service.d.ts +31 -0
  146. package/lib/api/query-processor/common-processors.service.d.ts +36 -0
  147. package/lib/api/query-processor/index.d.ts +2 -0
  148. package/lib/api/query-processor/query-processor.service.d.ts +18 -0
  149. package/lib/api/query-processor/tp-password-reset-processor.service.d.ts +15 -0
  150. package/lib/api/shared-contact-card.service.d.ts +33 -0
  151. package/lib/api/shared-contact-card2.gql.d.ts +36 -0
  152. package/lib/api/shared-contact-card2.service.d.ts +45 -0
  153. package/lib/api/time.service.d.ts +16 -0
  154. package/lib/api/types/graphql.types.d.ts +29 -0
  155. package/lib/api/types/index.d.ts +2 -0
  156. package/lib/api/types/lr-graphql.types.d.ts +385 -0
  157. package/lib/auth/auth.config.d.ts +5 -0
  158. package/lib/auth/auth.gql.d.ts +15 -0
  159. package/lib/auth/auth.types.d.ts +66 -0
  160. package/lib/auth/idle.service.d.ts +40 -0
  161. package/lib/auth/idle.types.d.ts +10 -0
  162. package/lib/auth/lbop.service.d.ts +91 -0
  163. package/lib/auth/life-ready-auth.service.d.ts +46 -0
  164. package/lib/auth/password.service.d.ts +78 -0
  165. package/lib/auth/register.service.d.ts +25 -0
  166. package/lib/auth/two-factor.service.d.ts +15 -0
  167. package/lib/category/category-meta.service.d.ts +23 -0
  168. package/lib/category/category.gql.d.ts +45 -0
  169. package/lib/category/category.service.d.ts +67 -0
  170. package/lib/category/category.types.d.ts +79 -0
  171. package/lib/cryptography/cryptography.types.d.ts +83 -0
  172. package/lib/cryptography/encryption.service.d.ts +41 -0
  173. package/lib/cryptography/key-factory.service.d.ts +38 -0
  174. package/lib/cryptography/key-graph.service.d.ts +33 -0
  175. package/lib/cryptography/key-meta.service.d.ts +44 -0
  176. package/lib/cryptography/key.service.d.ts +36 -0
  177. package/lib/cryptography/slip39.service.d.ts +43 -0
  178. package/lib/cryptography/web-crypto.service.d.ts +5 -0
  179. package/lib/life-ready.config.d.ts +14 -0
  180. package/lib/life-ready.module.d.ts +5 -0
  181. package/lib/plan/plan.gql.d.ts +11 -0
  182. package/lib/plan/plan.service.d.ts +33 -0
  183. package/lib/plan/plan.types.d.ts +31 -0
  184. package/lib/record/record-attachment.service.d.ts +16 -0
  185. package/lib/record/record.gql.d.ts +14 -0
  186. package/lib/record/record.service.d.ts +25 -0
  187. package/lib/record/record.types.d.ts +57 -0
  188. package/lib/record-type/record-type.service.d.ts +11 -0
  189. package/lib/record-type/record-type.types.d.ts +50 -0
  190. package/lib/scenario/approvals/scenario-approval.gql.d.ts +7 -0
  191. package/lib/scenario/approvals/scenario-approval.types.d.ts +63 -0
  192. package/lib/scenario/approvals/scenario-approver.service.d.ts +32 -0
  193. package/lib/scenario/claimants/scenario-claimant.gql.d.ts +5 -0
  194. package/lib/scenario/claimants/scenario-claimant.service.d.ts +17 -0
  195. package/lib/scenario/claimants/scenario-claimant.types.d.ts +18 -0
  196. package/lib/scenario/receivers/scenario-receiver.gql.d.ts +8 -0
  197. package/lib/scenario/receivers/scenario-receiver.service.d.ts +30 -0
  198. package/lib/scenario/receivers/scenario-receiver.types.d.ts +54 -0
  199. package/lib/scenario/scenario-setup.service.d.ts +22 -0
  200. package/lib/scenario/scenario.gql.d.ts +34 -0
  201. package/lib/scenario/scenario.service.d.ts +58 -0
  202. package/lib/scenario/scenario.types.d.ts +217 -0
  203. package/lib/search/search.gql.d.ts +1 -0
  204. package/lib/search/search.service.d.ts +25 -0
  205. package/lib/search/search.types.d.ts +20 -0
  206. package/lib/trusted-parties/tp-password-reset-request.service.d.ts +20 -0
  207. package/lib/trusted-parties/tp-password-reset-user.service.d.ts +41 -0
  208. package/lib/trusted-parties/tp-password-reset.gql.d.ts +218 -0
  209. package/lib/trusted-parties/tp-password-reset.service.d.ts +131 -0
  210. package/lib/trusted-parties/trusted-party.gql.d.ts +9 -0
  211. package/lib/trusted-parties/trusted-party.service.d.ts +44 -0
  212. package/lib/trusted-parties/trusted-party.types.d.ts +102 -0
  213. package/lib/trusted-parties/trusted-party2.gql.d.ts +79 -0
  214. package/lib/trusted-parties/trusted-party2.service.d.ts +114 -0
  215. package/lib/users/profile-details.service.d.ts +21 -0
  216. package/lib/users/profile.gql.d.ts +11 -0
  217. package/lib/users/profile.service.d.ts +35 -0
  218. package/lib/users/profile.types.d.ts +96 -0
  219. package/lib/users/user.gql.d.ts +9 -0
  220. package/lib/users/user.service.d.ts +12 -0
  221. package/lib/users/user.types.d.ts +23 -0
  222. package/lifeready-core.d.ts +9 -0
  223. package/lifeready-core.metadata.json +1 -0
  224. package/package.json +29 -0
  225. package/public-api.d.ts +77 -0
@@ -0,0 +1,320 @@
1
+ import { __awaiter } from "tslib";
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { Inject, Injectable } from '@angular/core';
4
+ import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
5
+ import { ProfileService } from '../users/profile.service';
6
+ import { EncryptionService } from '../cryptography/encryption.service';
7
+ import { KeyGraphService } from '../cryptography/key-graph.service';
8
+ import { LR_CONFIG } from '../life-ready.config';
9
+ import { LrAuthException, LrBadArgumentException } from '../_common/exceptions';
10
+ import { LrApolloService } from './../api/lr-apollo.service';
11
+ import { PasswordChangeMutation, PasswordChangeRequestMutation, PasswordChangeConfigQuery, } from './auth.gql';
12
+ import { WebCryptoService } from '../cryptography/web-crypto.service';
13
+ import * as moment_ from 'moment';
14
+ import { IdleService } from '../auth/idle.service';
15
+ import { KeyFactoryService as KFS } from '../cryptography/key-factory.service';
16
+ import * as i0 from "@angular/core";
17
+ import * as i1 from "../life-ready.config";
18
+ import * as i2 from "@angular/common/http";
19
+ import * as i3 from "../api/lr-apollo.service";
20
+ import * as i4 from "@aws-amplify/auth/lib-esm/Auth";
21
+ import * as i5 from "../users/profile.service";
22
+ import * as i6 from "../cryptography/key-factory.service";
23
+ import * as i7 from "../cryptography/encryption.service";
24
+ import * as i8 from "../cryptography/key-graph.service";
25
+ import * as i9 from "../cryptography/web-crypto.service";
26
+ import * as i10 from "./idle.service";
27
+ // "why?" you ask: https://stackoverflow.com/questions/59735280/angular-8-moment-error-cannot-call-a-namespace-moment
28
+ const moment = moment_;
29
+ export class PasswordCheck {
30
+ }
31
+ export class PasswordService {
32
+ constructor(config, http, apollo, auth, profileService, keyFactory, encryptionService, keyGraph, webCryptoService, idleService) {
33
+ this.config = config;
34
+ this.http = http;
35
+ this.apollo = apollo;
36
+ this.auth = auth;
37
+ this.profileService = profileService;
38
+ this.keyFactory = keyFactory;
39
+ this.encryptionService = encryptionService;
40
+ this.keyGraph = keyGraph;
41
+ this.webCryptoService = webCryptoService;
42
+ this.idleService = idleService;
43
+ this.CLIENT_NONCE_LENGTH = 32;
44
+ }
45
+ checkPassword(password) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const { years } = this.passwordStrength(password);
48
+ return {
49
+ length: password.length,
50
+ timeToCrack: moment.duration({ years }),
51
+ passwordExposed: yield this.getExposureCount(password),
52
+ };
53
+ });
54
+ }
55
+ getExposureCount(password) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ const sha1Password = yield this.webCryptoService.stringDigest('SHA-1', password);
58
+ const first5sha1 = sha1Password.substring(0, 5);
59
+ const response = yield this.http
60
+ .get(`https://api.pwnedpasswords.com/range/${first5sha1}`, {
61
+ responseType: 'text',
62
+ })
63
+ .toPromise();
64
+ const results = new RegExp(`^(?:${sha1Password.substring(5)}:)(?<count>\\d+)$`, 'im').exec(response);
65
+ if (results) {
66
+ return +results.groups.count;
67
+ }
68
+ return 0;
69
+ });
70
+ }
71
+ getPassIdpString(passIdp) {
72
+ return passIdp.toJSON(true).k;
73
+ }
74
+ createPassKeyBundle(password) {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ const passIdpParams = yield this.keyFactory.createPassIdpParams();
77
+ const passIdp = (yield this.keyFactory.derivePassIdp(Object.assign({ password }, passIdpParams))).jwk;
78
+ const passKeyParams = yield this.keyFactory.createPassKeyParams();
79
+ const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, passKeyParams))).jwk;
80
+ const passIdpVerifier = yield this.keyFactory.createPkcSignKey();
81
+ const wrappedPassIdpVerifierPrk = yield this.encryptionService.encrypt(passKey, passIdpVerifier.toJSON(true));
82
+ // There are two formats that the private key can be represented in JWK:
83
+ // https://tools.ietf.org/html/rfc8017#page-9
84
+ // The second form is an optimization:
85
+ // https://crypto.stackexchange.com/questions/19413/what-are-dp-and-dq-in-encryption-by-rsa-in-c
86
+ return {
87
+ passKeyParams,
88
+ passKey,
89
+ passIdpParams,
90
+ passIdp,
91
+ passIdpVerifier,
92
+ wrappedPassIdpVerifierPrk,
93
+ };
94
+ });
95
+ }
96
+ /**
97
+ * We need to allow for interruption of the process at any point. Each API call can be considered
98
+ * atomic and either succeeds or fails.
99
+ *
100
+ * The LR server APIs use semaphore tokens for locking critical operations, so concurrent calls will
101
+ * fail.
102
+ *
103
+ * We assume the worst case for IdP API calls. So we use the semaphore token from LR to prevent
104
+ * concurrent calls to IdP APIs, but we have to assume that the IdP API calls will either succeed or
105
+ * fail within a reasonable amount of time.
106
+ *
107
+ * Each location where the server state changes can be a potential point of interruption.
108
+ * Potential points of interruption are marked with: --Potential Failure Point--
109
+ *
110
+ * Places for timeout:
111
+ * - Login age too old at call to: verifyPassword()
112
+ * - Login age too old at call to: changePasswordMutation()
113
+ * - Semaphore token expires at call to: changePasswordComplete()
114
+ *
115
+ * Tests:
116
+ * - Potential Failure Point 1: should be able to restart the process, user remains signed in.
117
+ * - Potential Failure Point 2: should enter recovery flow
118
+ * - Potential Failure Point 3: should enter recovery flow
119
+ * - Potential Failure Point 4: should enter recovery flow
120
+ *
121
+ */
122
+ isLoginRequired() {
123
+ return __awaiter(this, void 0, void 0, function* () {
124
+ const changePasswordConfig = yield this.getChangePasswordConfig();
125
+ const authTime = moment(changePasswordConfig.authTime);
126
+ const serverTime = moment(changePasswordConfig.serverTime);
127
+ const duration = moment.duration(serverTime.diff(authTime));
128
+ const seconds = duration.asSeconds();
129
+ if (seconds > changePasswordConfig.maxAuthAgeSeconds) {
130
+ return true;
131
+ }
132
+ else {
133
+ return false;
134
+ }
135
+ });
136
+ }
137
+ changePassword(password, newPassword) {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const cognitoUser = yield this.auth.currentAuthenticatedUser();
140
+ // Validation
141
+ // todo: Add this back in
142
+ // Note the passIdp will always have a random salt, so will always be different to the current passIdp.
143
+ if (password === newPassword) {
144
+ throw new LrBadArgumentException('New password is the same as the current one.');
145
+ }
146
+ const { currentUser } = yield this.profileService.getCurrentUser();
147
+ const { passIdp, signedChallenge } = yield this.verifyPassword(password, currentUser);
148
+ // --Potential Failure Point 1--
149
+ // verifyPassword() asks for a current password challenge hence changes server state.
150
+ // Place break points here to test the failure scenarios.
151
+ // Generate the new passIdp
152
+ const newPassKey = yield this.createPassKeyBundle(newPassword);
153
+ // Re-encrypt master key with new key
154
+ const masterKey = yield this.keyGraph.getKey(currentUser.currentUserKey.masterKey.id);
155
+ const newWrappedMasterKey = yield this.encryptionService.encrypt(newPassKey.passKey, masterKey.jwk.toJSON(true));
156
+ // If the IdP change password failed, we need to go into recovery mode by forcing
157
+ // a login. We can't logout the user just yet since the IdP password change needs
158
+ // the user to be logged in. We _can_ removed any persisted session values for the IdP
159
+ // but that seems like too much trouble.
160
+ const { token, newPassKeyId } = yield this.changePasswordMutation(signedChallenge, currentUser.currentUserKey.masterKey.id, newWrappedMasterKey, newPassKey);
161
+ // --Potential Failure Point 2--
162
+ // changePasswordMutation() uploads new keys and obtains a semaphore lock to prevent any other
163
+ // clients from performing IdP password change.
164
+ // Now we can do the IdP password change.
165
+ // todo: Add this back in
166
+ yield this.auth.changePassword(cognitoUser, this.getPassIdpString(passIdp), this.getPassIdpString(newPassKey.passIdp));
167
+ // --Potential Failure Point 3--
168
+ // IdP password change
169
+ // Note that changePassword() could throw an exception for a number of reason. It could throw
170
+ // a network timeout for example. But we don't know if it's the response that timed out and
171
+ // the idp password change was actually carried out. So we have to be extra conservative and
172
+ // only act on a clear success. Otherwise we go into recover mode.
173
+ yield this.changePasswordComplete(cognitoUser.getSignInUserSession().getAccessToken().getJwtToken(), true, token);
174
+ });
175
+ }
176
+ changePasswordComplete(accessToken, useNewPassword, token = null) {
177
+ return __awaiter(this, void 0, void 0, function* () {
178
+ return this.http
179
+ .post(`${this.config.authUrl}users/password-change-complete/`, Object.assign({ use_new_password: useNewPassword }, (token && { token })), {
180
+ headers: {
181
+ Authorization: `Bearer ${accessToken}`,
182
+ },
183
+ })
184
+ .toPromise();
185
+ });
186
+ }
187
+ getVerifierPrK(passKey, wrappedPrK) {
188
+ return __awaiter(this, void 0, void 0, function* () {
189
+ try {
190
+ const prkJson = yield this.encryptionService.decrypt(passKey, wrappedPrK);
191
+ return KFS.asKey(prkJson);
192
+ }
193
+ catch (error) {
194
+ throw new LrAuthException('Wrong current password');
195
+ }
196
+ });
197
+ }
198
+ verifyPassword(password, currentUser) {
199
+ return __awaiter(this, void 0, void 0, function* () {
200
+ // Get information from the server to prepare for password change.
201
+ const passwordRequest = yield this.apollo.mutate({
202
+ mutation: PasswordChangeRequestMutation,
203
+ variables: {},
204
+ });
205
+ // Get the old passKey so we can decrypt the old password verifier
206
+ const passKeyResult = yield this.keyFactory.derivePassKey(Object.assign({ password }, currentUser.currentUserKey.passKey.passKeyParams));
207
+ const verifierPrK = yield this.getVerifierPrK(passKeyResult.jwk, currentUser.currentUserKey.passKey.wrappedPassIdpVerifierPrk);
208
+ // Sign the server challenge to prove to the server we can decrypt the password verifier.
209
+ // Generate
210
+ const clientNonce = this.keyFactory.randomString(this.CLIENT_NONCE_LENGTH);
211
+ const signedChallenge = yield this.encryptionService.sign(verifierPrK, {
212
+ serverNonce: passwordRequest.passwordChangeRequest.challenge.serverNonce,
213
+ clientNonce,
214
+ });
215
+ const passIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password }, currentUser.currentUserKey.passKey.passIdpParams));
216
+ return {
217
+ passIdp: passIdpResult.jwk,
218
+ signedChallenge,
219
+ };
220
+ });
221
+ }
222
+ changePasswordMutation(signedChallenge, masterKeyId, newWrappedMasterKey, passKeyBundle) {
223
+ return __awaiter(this, void 0, void 0, function* () {
224
+ const response = yield this.apollo.mutate({
225
+ mutation: PasswordChangeMutation,
226
+ variables: {
227
+ input: {
228
+ signedChallenge: JSON.stringify(signedChallenge),
229
+ masterKeyId,
230
+ newWrappedMasterKey: JSON.stringify(newWrappedMasterKey),
231
+ newPassKey: {
232
+ passIdpParams: JSON.stringify(passKeyBundle.passIdpParams),
233
+ passIdpVerifierPbk: JSON.stringify(passKeyBundle.passIdpVerifier.toJSON()),
234
+ wrappedPassIdpVerifierPrk: JSON.stringify(passKeyBundle.wrappedPassIdpVerifierPrk),
235
+ passKeyParams: JSON.stringify(passKeyBundle.passKeyParams),
236
+ },
237
+ },
238
+ },
239
+ });
240
+ return {
241
+ token: response.passwordChange.token,
242
+ newPassKeyId: response.passwordChange.newPassKey.id,
243
+ };
244
+ });
245
+ }
246
+ getChangePasswordConfig() {
247
+ return __awaiter(this, void 0, void 0, function* () {
248
+ const res = yield this.apollo.query({
249
+ query: PasswordChangeConfigQuery,
250
+ });
251
+ const ret = res.passwordChangeConfig;
252
+ ret.authTime = new Date(ret.authTime);
253
+ ret.serverTime = new Date(ret.serverTime);
254
+ return ret;
255
+ });
256
+ }
257
+ passwordStrength(password) {
258
+ const upper = /[A-Z]/g;
259
+ const lower = /[a-z]/g;
260
+ const digit = /[0-9]/g;
261
+ const upperChoices = 26;
262
+ const lowerChoices = 26;
263
+ const digitChoices = 10;
264
+ const specialChoices = 30; // /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g
265
+ function instanceCount(str, re) {
266
+ return ((str || '').match(re) || []).length;
267
+ }
268
+ const uppers = instanceCount(password, upper);
269
+ const lowers = instanceCount(password, lower);
270
+ const digits = instanceCount(password, digit);
271
+ const specials = password.length - uppers - lowers - digits;
272
+ let choices = 0;
273
+ if (uppers) {
274
+ choices += upperChoices;
275
+ }
276
+ if (lowers) {
277
+ choices += lowerChoices;
278
+ }
279
+ if (digits) {
280
+ choices += digitChoices;
281
+ }
282
+ if (specials) {
283
+ choices += specialChoices;
284
+ }
285
+ if (password.length === 0) {
286
+ return {
287
+ years: 0,
288
+ // bits of entropy
289
+ bits: 0,
290
+ };
291
+ }
292
+ const permutations = Math.pow(choices, password.length);
293
+ const years = (54000 * permutations) /
294
+ Math.pow(upperChoices + lowerChoices + digitChoices, 12);
295
+ return {
296
+ years,
297
+ // bits of entropy
298
+ bits: Math.round(Math.log2(permutations)),
299
+ };
300
+ }
301
+ }
302
+ PasswordService.ɵprov = i0.ɵɵdefineInjectable({ factory: function PasswordService_Factory() { return new PasswordService(i0.ɵɵinject(i1.LR_CONFIG), i0.ɵɵinject(i2.HttpClient), i0.ɵɵinject(i3.LrApolloService), i0.ɵɵinject(i4.AuthClass), i0.ɵɵinject(i5.ProfileService), i0.ɵɵinject(i6.KeyFactoryService), i0.ɵɵinject(i7.EncryptionService), i0.ɵɵinject(i8.KeyGraphService), i0.ɵɵinject(i9.WebCryptoService), i0.ɵɵinject(i10.IdleService)); }, token: PasswordService, providedIn: "root" });
303
+ PasswordService.decorators = [
304
+ { type: Injectable, args: [{
305
+ providedIn: 'root',
306
+ },] }
307
+ ];
308
+ PasswordService.ctorParameters = () => [
309
+ { type: undefined, decorators: [{ type: Inject, args: [LR_CONFIG,] }] },
310
+ { type: HttpClient },
311
+ { type: LrApolloService },
312
+ { type: AuthClass },
313
+ { type: ProfileService },
314
+ { type: KFS },
315
+ { type: EncryptionService },
316
+ { type: KeyGraphService },
317
+ { type: WebCryptoService },
318
+ { type: IdleService }
319
+ ];
320
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3dvcmQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJDOi9Qcm9qZWN0cy90ZXN0L3Byb2plY3RzL2NvcmUvc3JjLyIsInNvdXJjZXMiOlsibGliL2F1dGgvcGFzc3dvcmQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRW5ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUUzRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDdkUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3BFLE9BQU8sRUFBbUIsU0FBUyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2hGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM3RCxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLDZCQUE2QixFQUM3Qix5QkFBeUIsR0FDMUIsTUFBTSxZQUFZLENBQUM7QUFFcEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFFdEUsT0FBTyxLQUFLLE9BQU8sTUFBTSxRQUFRLENBQUM7QUFFbEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxpQkFBaUIsSUFBSSxHQUFHLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7Ozs7Ozs7Ozs7O0FBRS9FLHFIQUFxSDtBQUNySCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUM7QUF5QnZCLE1BQU0sT0FBTyxhQUFhO0NBSXpC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QyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQ3pCLE9BQU87Z0JBQ0wsS0FBSyxFQUFFLENBQUM7Z0JBQ1Isa0JBQWtCO2dCQUNsQixJQUFJLEVBQUUsQ0FBQzthQUNSLENBQUM7U0FDSDtRQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV4RCxNQUFNLEtBQUssR0FDVCxDQUFDLEtBQUssR0FBRyxZQUFZLENBQUM7WUFDdEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEdBQUcsWUFBWSxHQUFHLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMzRCxPQUFPO1lBQ0wsS0FBSztZQUNMLGtCQUFrQjtZQUNsQixJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQzFDLENBQUM7SUFDSixDQUFDOzs7O1lBNVhGLFVBQVUsU0FBQztnQkFDVixVQUFVLEVBQUUsTUFBTTthQUNuQjs7OzRDQUtJLE1BQU0sU0FBQyxTQUFTO1lBL0RaLFVBQVU7WUFVVixlQUFlO1lBUGYsU0FBUztZQUVULGNBQWM7WUFpQk8sR0FBRztZQWhCeEIsaUJBQWlCO1lBQ2pCLGVBQWU7WUFVZixnQkFBZ0I7WUFJaEIsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb2duaXRvVXNlciB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9hdXRoJztcclxuaW1wb3J0IHsgQXV0aENsYXNzIH0gZnJvbSAnQGF3cy1hbXBsaWZ5L2F1dGgvbGliLWVzbS9BdXRoJztcclxuaW1wb3J0IHsgSldLLCBKV1MgfSBmcm9tICdub2RlLWpvc2UnO1xyXG5pbXBvcnQgeyBQcm9maWxlU2VydmljZSB9IGZyb20gJy4uL3VzZXJzL3Byb2ZpbGUuc2VydmljZSc7XHJcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2VuY3J5cHRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IEtleUdyYXBoU2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZ3JhcGguc2VydmljZSc7XHJcbmltcG9ydCB7IExpZmVSZWFkeUNvbmZpZywgTFJfQ09ORklHIH0gZnJvbSAnLi4vbGlmZS1yZWFkeS5jb25maWcnO1xyXG5pbXBvcnQgeyBMckF1dGhFeGNlcHRpb24sIExyQmFkQXJndW1lbnRFeGNlcHRpb24gfSBmcm9tICcuLi9fY29tbW9uL2V4Y2VwdGlvbnMnO1xyXG5pbXBvcnQgeyBMckFwb2xsb1NlcnZpY2UgfSBmcm9tICcuLy4uL2FwaS9sci1hcG9sbG8uc2VydmljZSc7XHJcbmltcG9ydCB7XHJcbiAgUGFzc3dvcmRDaGFuZ2VNdXRhdGlvbixcclxuICBQYXNzd29yZENoYW5nZVJlcXVlc3RNdXRhdGlvbixcclxuICBQYXNzd29yZENoYW5nZUNvbmZpZ1F1ZXJ5LFxyXG59IGZyb20gJy4vYXV0aC5ncWwnO1xyXG5pbXBvcnQgeyBQYXNzS2V5QnVuZGxlIH0gZnJvbSAnLi9hdXRoLnR5cGVzJztcclxuaW1wb3J0IHsgV2ViQ3J5cHRvU2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS93ZWItY3J5cHRvLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBEdXJhdGlvbiB9IGZyb20gJ21vbWVudCc7XHJcbmltcG9ydCAqIGFzIG1vbWVudF8gZnJvbSAnbW9tZW50JztcclxuaW1wb3J0IHsgQXBpQ3VycmVudFVzZXIgfSBmcm9tICcuLi91c2Vycy9wcm9maWxlLnR5cGVzJztcclxuaW1wb3J0IHsgSWRsZVNlcnZpY2UgfSBmcm9tICcuLi9hdXRoL2lkbGUuc2VydmljZSc7XHJcbmltcG9ydCB7IEtleUZhY3RvcnlTZXJ2aWNlIGFzIEtGUyB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZmFjdG9yeS5zZXJ2aWNlJztcclxuXHJcbi8vIFwid2h5P1wiIHlvdSBhc2s6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzU5NzM1MjgwL2FuZ3VsYXItOC1tb21lbnQtZXJyb3ItY2Fubm90LWNhbGwtYS1uYW1lc3BhY2UtbW9tZW50XHJcbmNvbnN0IG1vbWVudCA9IG1vbWVudF87XHJcblxyXG5pbnRlcmZhY2UgUGFzc3dvcmRDaGFuZ2VSZXF1ZXN0TXV0YXRpb24ge1xyXG4gIHBhc3N3b3JkQ2hhbmdlUmVxdWVzdDoge1xyXG4gICAgY2hhbGxlbmdlOiB7XHJcbiAgICAgIHNlcnZlck5vbmNlOiBzdHJpbmc7XHJcbiAgICB9O1xyXG4gIH07XHJcbn1cclxuXHJcbmludGVyZmFjZSBQYXNzd29yZENoYW5nZU11dGF0aW9uIHtcclxuICBwYXNzd29yZENoYW5nZToge1xyXG4gICAgdG9rZW46IHN0cmluZztcclxuICAgIG5ld1Bhc3NLZXk6IHtcclxuICAgICAgaWQ6IHN0cmluZztcclxuICAgIH07XHJcbiAgfTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBQYXNzd29yZENoYW5nZUNvbmZpZyB7XHJcbiAgbWF4QXV0aEFnZVNlY29uZHM6IG51bWJlcjtcclxuICBhdXRoVGltZTogc3RyaW5nIHwgRGF0ZTtcclxuICBzZXJ2ZXJUaW1lOiBzdHJpbmcgfCBEYXRlO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgUGFzc3dvcmRDaGVjayB7XHJcbiAgbGVuZ3RoPzogbnVtYmVyO1xyXG4gIHRpbWVUb0NyYWNrPzogRHVyYXRpb247XHJcbiAgcGFzc3dvcmRFeHBvc2VkPzogbnVtYmVyO1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgUGFzc3dvcmRTZXJ2aWNlIHtcclxuICBwcml2YXRlIHJlYWRvbmx5IENMSUVOVF9OT05DRV9MRU5HVEggPSAzMjtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0KExSX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IExpZmVSZWFkeUNvbmZpZyxcclxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcclxuICAgIHByaXZhdGUgYXBvbGxvOiBMckFwb2xsb1NlcnZpY2UsXHJcbiAgICBwcml2YXRlIGF1dGg6IEF1dGhDbGFzcyxcclxuICAgIHByaXZhdGUgcHJvZmlsZVNlcnZpY2U6IFByb2ZpbGVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBrZXlGYWN0b3J5OiBLRlMsXHJcbiAgICBwcml2YXRlIGVuY3J5cHRpb25TZXJ2aWNlOiBFbmNyeXB0aW9uU2VydmljZSxcclxuICAgIHByaXZhdGUga2V5R3JhcGg6IEtleUdyYXBoU2VydmljZSxcclxuICAgIHByaXZhdGUgd2ViQ3J5cHRvU2VydmljZTogV2ViQ3J5cHRvU2VydmljZSxcclxuICAgIHByaXZhdGUgaWRsZVNlcnZpY2U6IElkbGVTZXJ2aWNlXHJcbiAgKSB7fVxyXG5cclxuICBwdWJsaWMgYXN5bmMgY2hlY2tQYXNzd29yZChwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxQYXNzd29yZENoZWNrPiB7XHJcbiAgICBjb25zdCB7IHllYXJzIH0gPSB0aGlzLnBhc3N3b3JkU3RyZW5ndGgocGFzc3dvcmQpO1xyXG5cclxuICAgIHJldHVybiB7XHJcbiAgICAgIGxlbmd0aDogcGFzc3dvcmQubGVuZ3RoLFxyXG4gICAgICB0aW1lVG9DcmFjazogbW9tZW50LmR1cmF0aW9uKHsgeWVhcnMgfSksXHJcbiAgICAgIHBhc3N3b3JkRXhwb3NlZDogYXdhaXQgdGhpcy5nZXRFeHBvc3VyZUNvdW50KHBhc3N3b3JkKSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RXhwb3N1cmVDb3VudChwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcclxuICAgIGNvbnN0IHNoYTFQYXNzd29yZCA9IGF3YWl0IHRoaXMud2ViQ3J5cHRvU2VydmljZS5zdHJpbmdEaWdlc3QoXHJcbiAgICAgICdTSEEtMScsXHJcbiAgICAgIHBhc3N3b3JkXHJcbiAgICApO1xyXG4gICAgY29uc3QgZmlyc3Q1c2hhMSA9IHNoYTFQYXNzd29yZC5zdWJzdHJpbmcoMCwgNSk7XHJcblxyXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmh0dHBcclxuICAgICAgLmdldChgaHR0cHM6Ly9hcGkucHduZWRwYXNzd29yZHMuY29tL3JhbmdlLyR7Zmlyc3Q1c2hhMX1gLCB7XHJcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCcsXHJcbiAgICAgIH0pXHJcbiAgICAgIC50b1Byb21pc2UoKTtcclxuXHJcbiAgICBjb25zdCByZXN1bHRzID0gbmV3IFJlZ0V4cChcclxuICAgICAgYF4oPzoke3NoYTFQYXNzd29yZC5zdWJzdHJpbmcoNSl9OikoPzxjb3VudD5cXFxcZCspJGAsXHJcbiAgICAgICdpbSdcclxuICAgICkuZXhlYyhyZXNwb25zZSk7XHJcblxyXG4gICAgaWYgKHJlc3VsdHMpIHtcclxuICAgICAgcmV0dXJuICtyZXN1bHRzLmdyb3Vwcy5jb3VudDtcclxuICAgIH1cclxuICAgIHJldHVybiAwO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGdldFBhc3NJZHBTdHJpbmcocGFzc0lkcDogSldLLktleSkge1xyXG4gICAgcmV0dXJuIChwYXNzSWRwLnRvSlNPTih0cnVlKSBhcyBhbnkpLms7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgY3JlYXRlUGFzc0tleUJ1bmRsZShwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxQYXNzS2V5QnVuZGxlPiB7XHJcbiAgICBjb25zdCBwYXNzSWRwUGFyYW1zID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZVBhc3NJZHBQYXJhbXMoKTtcclxuICAgIGNvbnN0IHBhc3NJZHAgPSAoXHJcbiAgICAgIGF3YWl0IHRoaXMua2V5RmFjdG9yeS5kZXJpdmVQYXNzSWRwKHtcclxuICAgICAgICBwYXNzd29yZCxcclxuICAgICAgICAuLi5wYXNzSWRwUGFyYW1zLFxyXG4gICAgICB9KVxyXG4gICAgKS5qd2s7XHJcblxyXG4gICAgY29uc3QgcGFzc0tleVBhcmFtcyA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVQYXNzS2V5UGFyYW1zKCk7XHJcbiAgICBjb25zdCBwYXNzS2V5ID0gKFxyXG4gICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XHJcbiAgICAgICAgcGFzc3dvcmQsXHJcbiAgICAgICAgLi4ucGFzc0tleVBhcmFtcyxcclxuICAgICAgfSlcclxuICAgICkuandrO1xyXG5cclxuICAgIGNvbnN0IHBhc3NJZHBWZXJpZmllciA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVQa2NTaWduS2V5KCk7XHJcblxyXG4gICAgY29uc3Qgd3JhcHBlZFBhc3NJZHBWZXJpZmllclByayA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcclxuICAgICAgcGFzc0tleSxcclxuICAgICAgcGFzc0lkcFZlcmlmaWVyLnRvSlNPTih0cnVlKVxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBUaGVyZSBhcmUgdHdvIGZvcm1hdHMgdGhhdCB0aGUgcHJpdmF0ZSBrZXkgY2FuIGJlIHJlcHJlc2VudGVkIGluIEpXSzpcclxuICAgIC8vIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM4MDE3I3BhZ2UtOVxyXG4gICAgLy8gVGhlIHNlY29uZCBmb3JtIGlzIGFuIG9wdGltaXphdGlvbjpcclxuICAgIC8vIGh0dHBzOi8vY3J5cHRvLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy8xOTQxMy93aGF0LWFyZS1kcC1hbmQtZHEtaW4tZW5jcnlwdGlvbi1ieS1yc2EtaW4tY1xyXG5cclxuICAgIHJldHVybiB7XHJcbiAgICAgIHBhc3NLZXlQYXJhbXMsXHJcbiAgICAgIHBhc3NLZXksXHJcbiAgICAgIHBhc3NJZHBQYXJhbXMsXHJcbiAgICAgIHBhc3NJZHAsXHJcbiAgICAgIHBhc3NJZHBWZXJpZmllcixcclxuICAgICAgd3JhcHBlZFBhc3NJZHBWZXJpZmllclByayxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBXZSBuZWVkIHRvIGFsbG93IGZvciBpbnRlcnJ1cHRpb24gb2YgdGhlIHByb2Nlc3MgYXQgYW55IHBvaW50LiBFYWNoIEFQSSBjYWxsIGNhbiBiZSBjb25zaWRlcmVkXHJcbiAgICogYXRvbWljIGFuZCBlaXRoZXIgc3VjY2VlZHMgb3IgZmFpbHMuXHJcbiAgICpcclxuICAgKiBUaGUgTFIgc2VydmVyIEFQSXMgdXNlIHNlbWFwaG9yZSB0b2tlbnMgZm9yIGxvY2tpbmcgY3JpdGljYWwgb3BlcmF0aW9ucywgc28gY29uY3VycmVudCBjYWxscyB3aWxsXHJcbiAgICogZmFpbC5cclxuICAgKlxyXG4gICAqIFdlIGFzc3VtZSB0aGUgd29yc3QgY2FzZSBmb3IgSWRQIEFQSSBjYWxscy4gU28gd2UgdXNlIHRoZSBzZW1hcGhvcmUgdG9rZW4gZnJvbSBMUiB0byBwcmV2ZW50XHJcbiAgICogY29uY3VycmVudCBjYWxscyB0byBJZFAgQVBJcywgYnV0IHdlIGhhdmUgdG8gYXNzdW1lIHRoYXQgdGhlIElkUCBBUEkgY2FsbHMgd2lsbCBlaXRoZXIgc3VjY2VlZCBvclxyXG4gICAqIGZhaWwgd2l0aGluIGEgcmVhc29uYWJsZSBhbW91bnQgb2YgdGltZS5cclxuICAgKlxyXG4gICAqIEVhY2ggbG9jYXRpb24gd2hlcmUgdGhlIHNlcnZlciBzdGF0ZSBjaGFuZ2VzIGNhbiBiZSBhIHBvdGVudGlhbCBwb2ludCBvZiBpbnRlcnJ1cHRpb24uXHJcbiAgICogUG90ZW50aWFsIHBvaW50cyBvZiBpbnRlcnJ1cHRpb24gYXJlIG1hcmtlZCB3aXRoOiAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50LS1cclxuICAgKlxyXG4gICAqIFBsYWNlcyBmb3IgdGltZW91dDpcclxuICAgKiAtIExvZ2luIGFnZSB0b28gb2xkIGF0IGNhbGwgdG86IHZlcmlmeVBhc3N3b3JkKClcclxuICAgKiAtIExvZ2luIGFnZSB0b28gb2xkIGF0IGNhbGwgdG86IGNoYW5nZVBhc3N3b3JkTXV0YXRpb24oKVxyXG4gICAqIC0gU2VtYXBob3JlIHRva2VuIGV4cGlyZXMgYXQgY2FsbCB0bzogY2hhbmdlUGFzc3dvcmRDb21wbGV0ZSgpXHJcbiAgICpcclxuICAgKiBUZXN0czpcclxuICAgKiAtIFBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDE6IHNob3VsZCBiZSBhYmxlIHRvIHJlc3RhcnQgdGhlIHByb2Nlc3MsIHVzZXIgcmVtYWlucyBzaWduZWQgaW4uXHJcbiAgICogLSBQb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAyOiBzaG91bGQgZW50ZXIgcmVjb3ZlcnkgZmxvd1xyXG4gICAqIC0gUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgMzogc2hvdWxkIGVudGVyIHJlY292ZXJ5IGZsb3dcclxuICAgKiAtIFBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDQ6IHNob3VsZCBlbnRlciByZWNvdmVyeSBmbG93XHJcbiAgICpcclxuICAgKi9cclxuXHJcbiAgcHVibGljIGFzeW5jIGlzTG9naW5SZXF1aXJlZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuICAgIGNvbnN0IGNoYW5nZVBhc3N3b3JkQ29uZmlnID0gYXdhaXQgdGhpcy5nZXRDaGFuZ2VQYXNzd29yZENvbmZpZygpO1xyXG4gICAgY29uc3QgYXV0aFRpbWUgPSBtb21lbnQoY2hhbmdlUGFzc3dvcmRDb25maWcuYXV0aFRpbWUpO1xyXG4gICAgY29uc3Qgc2VydmVyVGltZSA9IG1vbWVudChjaGFuZ2VQYXNzd29yZENvbmZpZy5zZXJ2ZXJUaW1lKTtcclxuICAgIGNvbnN0IGR1cmF0aW9uID0gbW9tZW50LmR1cmF0aW9uKHNlcnZlclRpbWUuZGlmZihhdXRoVGltZSkpO1xyXG4gICAgY29uc3Qgc2Vjb25kcyA9IGR1cmF0aW9uLmFzU2Vjb25kcygpO1xyXG4gICAgaWYgKHNlY29uZHMgPiBjaGFuZ2VQYXNzd29yZENvbmZpZy5tYXhBdXRoQWdlU2Vjb25kcykge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBjaGFuZ2VQYXNzd29yZChwYXNzd29yZDogc3RyaW5nLCBuZXdQYXNzd29yZDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XHJcblxyXG4gICAgLy8gVmFsaWRhdGlvblxyXG4gICAgLy8gdG9kbzogQWRkIHRoaXMgYmFjayBpblxyXG4gICAgLy8gTm90ZSB0aGUgcGFzc0lkcCB3aWxsIGFsd2F5cyBoYXZlIGEgcmFuZG9tIHNhbHQsIHNvIHdpbGwgYWx3YXlzIGJlIGRpZmZlcmVudCB0byB0aGUgY3VycmVudCBwYXNzSWRwLlxyXG4gICAgaWYgKHBhc3N3b3JkID09PSBuZXdQYXNzd29yZCkge1xyXG4gICAgICB0aHJvdyBuZXcgTHJCYWRBcmd1bWVudEV4Y2VwdGlvbihcclxuICAgICAgICAnTmV3IHBhc3N3b3JkIGlzIHRoZSBzYW1lIGFzIHRoZSBjdXJyZW50IG9uZS4nXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeyBjdXJyZW50VXNlciB9ID0gYXdhaXQgdGhpcy5wcm9maWxlU2VydmljZS5nZXRDdXJyZW50VXNlcigpO1xyXG5cclxuICAgIGNvbnN0IHsgcGFzc0lkcCwgc2lnbmVkQ2hhbGxlbmdlIH0gPSBhd2FpdCB0aGlzLnZlcmlmeVBhc3N3b3JkKFxyXG4gICAgICBwYXNzd29yZCxcclxuICAgICAgY3VycmVudFVzZXJcclxuICAgICk7XHJcblxyXG4gICAgLy8gLS1Qb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAxLS1cclxuICAgIC8vIHZlcmlmeVBhc3N3b3JkKCkgYXNrcyBmb3IgYSBjdXJyZW50IHBhc3N3b3JkIGNoYWxsZW5nZSBoZW5jZSBjaGFuZ2VzIHNlcnZlciBzdGF0ZS5cclxuICAgIC8vIFBsYWNlIGJyZWFrIHBvaW50cyBoZXJlIHRvIHRlc3QgdGhlIGZhaWx1cmUgc2NlbmFyaW9zLlxyXG5cclxuICAgIC8vIEdlbmVyYXRlIHRoZSBuZXcgcGFzc0lkcFxyXG4gICAgY29uc3QgbmV3UGFzc0tleSA9IGF3YWl0IHRoaXMuY3JlYXRlUGFzc0tleUJ1bmRsZShuZXdQYXNzd29yZCk7XHJcblxyXG4gICAgLy8gUmUtZW5jcnlwdCBtYXN0ZXIga2V5IHdpdGggbmV3IGtleVxyXG4gICAgY29uc3QgbWFzdGVyS2V5ID0gYXdhaXQgdGhpcy5rZXlHcmFwaC5nZXRLZXkoXHJcbiAgICAgIGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5Lm1hc3RlcktleS5pZFxyXG4gICAgKTtcclxuICAgIGNvbnN0IG5ld1dyYXBwZWRNYXN0ZXJLZXkgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXHJcbiAgICAgIG5ld1Bhc3NLZXkucGFzc0tleSxcclxuICAgICAgbWFzdGVyS2V5Lmp3ay50b0pTT04odHJ1ZSlcclxuICAgICk7XHJcblxyXG4gICAgLy8gSWYgdGhlIElkUCBjaGFuZ2UgcGFzc3dvcmQgZmFpbGVkLCB3ZSBuZWVkIHRvIGdvIGludG8gcmVjb3ZlcnkgbW9kZSBieSBmb3JjaW5nXHJcbiAgICAvLyBhIGxvZ2luLiBXZSBjYW4ndCBsb2dvdXQgdGhlIHVzZXIganVzdCB5ZXQgc2luY2UgdGhlIElkUCBwYXNzd29yZCBjaGFuZ2UgbmVlZHNcclxuICAgIC8vIHRoZSB1c2VyIHRvIGJlIGxvZ2dlZCBpbi4gV2UgX2Nhbl8gcmVtb3ZlZCBhbnkgcGVyc2lzdGVkIHNlc3Npb24gdmFsdWVzIGZvciB0aGUgSWRQXHJcbiAgICAvLyBidXQgdGhhdCBzZWVtcyBsaWtlIHRvbyBtdWNoIHRyb3VibGUuXHJcblxyXG4gICAgY29uc3QgeyB0b2tlbiwgbmV3UGFzc0tleUlkIH0gPSBhd2FpdCB0aGlzLmNoYW5nZVBhc3N3b3JkTXV0YXRpb24oXHJcbiAgICAgIHNpZ25lZENoYWxsZW5nZSxcclxuICAgICAgY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkubWFzdGVyS2V5LmlkLFxyXG4gICAgICBuZXdXcmFwcGVkTWFzdGVyS2V5LFxyXG4gICAgICBuZXdQYXNzS2V5XHJcbiAgICApO1xyXG5cclxuICAgIC8vIC0tUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgMi0tXHJcbiAgICAvLyBjaGFuZ2VQYXNzd29yZE11dGF0aW9uKCkgdXBsb2FkcyBuZXcga2V5cyBhbmQgb2J0YWlucyBhIHNlbWFwaG9yZSBsb2NrIHRvIHByZXZlbnQgYW55IG90aGVyXHJcbiAgICAvLyBjbGllbnRzIGZyb20gcGVyZm9ybWluZyBJZFAgcGFzc3dvcmQgY2hhbmdlLlxyXG5cclxuICAgIC8vIE5vdyB3ZSBjYW4gZG8gdGhlIElkUCBwYXNzd29yZCBjaGFuZ2UuXHJcbiAgICAvLyB0b2RvOiBBZGQgdGhpcyBiYWNrIGluXHJcbiAgICBhd2FpdCB0aGlzLmF1dGguY2hhbmdlUGFzc3dvcmQoXHJcbiAgICAgIGNvZ25pdG9Vc2VyLFxyXG4gICAgICB0aGlzLmdldFBhc3NJZHBTdHJpbmcocGFzc0lkcCksXHJcbiAgICAgIHRoaXMuZ2V0UGFzc0lkcFN0cmluZyhuZXdQYXNzS2V5LnBhc3NJZHApXHJcbiAgICApO1xyXG5cclxuICAgIC8vIC0tUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgMy0tXHJcbiAgICAvLyBJZFAgcGFzc3dvcmQgY2hhbmdlXHJcblxyXG4gICAgLy8gTm90ZSB0aGF0IGNoYW5nZVBhc3N3b3JkKCkgY291bGQgdGhyb3cgYW4gZXhjZXB0aW9uIGZvciBhIG51bWJlciBvZiByZWFzb24uIEl0IGNvdWxkIHRocm93XHJcbiAgICAvLyBhIG5ldHdvcmsgdGltZW91dCBmb3IgZXhhbXBsZS4gQnV0IHdlIGRvbid0IGtub3cgaWYgaXQncyB0aGUgcmVzcG9uc2UgdGhhdCB0aW1lZCBvdXQgYW5kXHJcbiAgICAvLyB0aGUgaWRwIHBhc3N3b3JkIGNoYW5nZSB3YXMgYWN0dWFsbHkgY2FycmllZCBvdXQuIFNvIHdlIGhhdmUgdG8gYmUgZXh0cmEgY29uc2VydmF0aXZlIGFuZFxyXG4gICAgLy8gb25seSBhY3Qgb24gYSBjbGVhciBzdWNjZXNzLiBPdGhlcndpc2Ugd2UgZ28gaW50byByZWNvdmVyIG1vZGUuXHJcbiAgICBhd2FpdCB0aGlzLmNoYW5nZVBhc3N3b3JkQ29tcGxldGUoXHJcbiAgICAgIGNvZ25pdG9Vc2VyLmdldFNpZ25JblVzZXJTZXNzaW9uKCkuZ2V0QWNjZXNzVG9rZW4oKS5nZXRKd3RUb2tlbigpLFxyXG4gICAgICB0cnVlLFxyXG4gICAgICB0b2tlblxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBjaGFuZ2VQYXNzd29yZENvbXBsZXRlKFxyXG4gICAgYWNjZXNzVG9rZW46IHN0cmluZyxcclxuICAgIHVzZU5ld1Bhc3N3b3JkOiBib29sZWFuLFxyXG4gICAgdG9rZW46IHN0cmluZyA9IG51bGxcclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cFxyXG4gICAgICAucG9zdChcclxuICAgICAgICBgJHt0aGlzLmNvbmZpZy5hdXRoVXJsfXVzZXJzL3Bhc3N3b3JkLWNoYW5nZS1jb21wbGV0ZS9gLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHVzZV9uZXdfcGFzc3dvcmQ6IHVzZU5ld1Bhc3N3b3JkLFxyXG4gICAgICAgICAgLi4uKHRva2VuICYmIHsgdG9rZW4gfSksXHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBoZWFkZXJzOiB7XHJcbiAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthY2Nlc3NUb2tlbn1gLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9XHJcbiAgICAgIClcclxuICAgICAgLnRvUHJvbWlzZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBnZXRWZXJpZmllclBySyhcclxuICAgIHBhc3NLZXk6IEpXSy5LZXksXHJcbiAgICB3cmFwcGVkUHJLOiBvYmplY3RcclxuICApOiBQcm9taXNlPEpXSy5LZXk+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHBya0pzb24gPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQocGFzc0tleSwgd3JhcHBlZFBySyk7XHJcbiAgICAgIHJldHVybiBLRlMuYXNLZXkocHJrSnNvbik7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICB0aHJvdyBuZXcgTHJBdXRoRXhjZXB0aW9uKCdXcm9uZyBjdXJyZW50IHBhc3N3b3JkJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIHZlcmlmeVBhc3N3b3JkKFxyXG4gICAgcGFzc3dvcmQ6IHN0cmluZyxcclxuICAgIGN1cnJlbnRVc2VyOiBBcGlDdXJyZW50VXNlclxyXG4gICk6IFByb21pc2U8eyBwYXNzSWRwOiBKV0suS2V5OyBzaWduZWRDaGFsbGVuZ2U6IEpXUy5DcmVhdGVTaWduUmVzdWx0IH0+IHtcclxuICAgIC8vIEdldCBpbmZvcm1hdGlvbiBmcm9tIHRoZSBzZXJ2ZXIgdG8gcHJlcGFyZSBmb3IgcGFzc3dvcmQgY2hhbmdlLlxyXG4gICAgY29uc3QgcGFzc3dvcmRSZXF1ZXN0ID0gYXdhaXQgdGhpcy5hcG9sbG8ubXV0YXRlPFBhc3N3b3JkQ2hhbmdlUmVxdWVzdE11dGF0aW9uPihcclxuICAgICAge1xyXG4gICAgICAgIG11dGF0aW9uOiBQYXNzd29yZENoYW5nZVJlcXVlc3RNdXRhdGlvbixcclxuICAgICAgICB2YXJpYWJsZXM6IHt9LFxyXG4gICAgICB9XHJcbiAgICApO1xyXG5cclxuICAgIC8vIEdldCB0aGUgb2xkIHBhc3NLZXkgc28gd2UgY2FuIGRlY3J5cHQgdGhlIG9sZCBwYXNzd29yZCB2ZXJpZmllclxyXG4gICAgY29uc3QgcGFzc0tleVJlc3VsdCA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5kZXJpdmVQYXNzS2V5KHtcclxuICAgICAgcGFzc3dvcmQsXHJcbiAgICAgIC4uLmN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LnBhc3NLZXkucGFzc0tleVBhcmFtcyxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHZlcmlmaWVyUHJLID0gYXdhaXQgdGhpcy5nZXRWZXJpZmllclBySyhcclxuICAgICAgcGFzc0tleVJlc3VsdC5qd2ssXHJcbiAgICAgIGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LnBhc3NLZXkud3JhcHBlZFBhc3NJZHBWZXJpZmllclBya1xyXG4gICAgKTtcclxuXHJcbiAgICAvLyBTaWduIHRoZSBzZXJ2ZXIgY2hhbGxlbmdlIHRvIHByb3ZlIHRvIHRoZSBzZXJ2ZXIgd2UgY2FuIGRlY3J5cHQgdGhlIHBhc3N3b3JkIHZlcmlmaWVyLlxyXG4gICAgLy8gR2VuZXJhdGVcclxuICAgIGNvbnN0IGNsaWVudE5vbmNlID0gdGhpcy5rZXlGYWN0b3J5LnJhbmRvbVN0cmluZyh0aGlzLkNMSUVOVF9OT05DRV9MRU5HVEgpO1xyXG5cclxuICAgIGNvbnN0IHNpZ25lZENoYWxsZW5nZSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2Uuc2lnbih2ZXJpZmllclBySywge1xyXG4gICAgICBzZXJ2ZXJOb25jZTogcGFzc3dvcmRSZXF1ZXN0LnBhc3N3b3JkQ2hhbmdlUmVxdWVzdC5jaGFsbGVuZ2Uuc2VydmVyTm9uY2UsXHJcbiAgICAgIGNsaWVudE5vbmNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgcGFzc0lkcFJlc3VsdCA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5kZXJpdmVQYXNzSWRwKHtcclxuICAgICAgcGFzc3dvcmQsXHJcbiAgICAgIC4uLmN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LnBhc3NLZXkucGFzc0lkcFBhcmFtcyxcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiB7XHJcbiAgICAgIHBhc3NJZHA6IHBhc3NJZHBSZXN1bHQuandrLFxyXG4gICAgICBzaWduZWRDaGFsbGVuZ2UsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBjaGFuZ2VQYXNzd29yZE11dGF0aW9uKFxyXG4gICAgc2lnbmVkQ2hhbGxlbmdlOiBKV1MuQ3JlYXRlU2lnblJlc3VsdCxcclxuICAgIG1hc3RlcktleUlkOiBzdHJpbmcsXHJcbiAgICBuZXdXcmFwcGVkTWFzdGVyS2V5OiBvYmplY3QsXHJcbiAgICBwYXNzS2V5QnVuZGxlOiBQYXNzS2V5QnVuZGxlXHJcbiAgKTogUHJvbWlzZTx7IHRva2VuOiBzdHJpbmc7IG5ld1Bhc3NLZXlJZDogc3RyaW5nIH0+IHtcclxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5hcG9sbG8ubXV0YXRlPFBhc3N3b3JkQ2hhbmdlTXV0YXRpb24+KHtcclxuICAgICAgbXV0YXRpb246IFBhc3N3b3JkQ2hhbmdlTXV0YXRpb24sXHJcbiAgICAgIHZhcmlhYmxlczoge1xyXG4gICAgICAgIGlucHV0OiB7XHJcbiAgICAgICAgICBzaWduZWRDaGFsbGVuZ2U6IEpTT04uc3RyaW5naWZ5KHNpZ25lZENoYWxsZW5nZSksXHJcbiAgICAgICAgICBtYXN0ZXJLZXlJZCxcclxuICAgICAgICAgIG5ld1dyYXBwZWRNYXN0ZXJLZXk6IEpTT04uc3RyaW5naWZ5KG5ld1dyYXBwZWRNYXN0ZXJLZXkpLFxyXG4gICAgICAgICAgbmV3UGFzc0tleToge1xyXG4gICAgICAgICAgICBwYXNzSWRwUGFyYW1zOiBKU09OLnN0cmluZ2lmeShwYXNzS2V5QnVuZGxlLnBhc3NJZHBQYXJhbXMpLFxyXG4gICAgICAgICAgICBwYXNzSWRwVmVyaWZpZXJQYms6IEpTT04uc3RyaW5naWZ5KFxyXG4gICAgICAgICAgICAgIHBhc3NLZXlCdW5kbGUucGFzc0lkcFZlcmlmaWVyLnRvSlNPTigpXHJcbiAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgIHdyYXBwZWRQYXNzSWRwVmVyaWZpZXJQcms6IEpTT04uc3RyaW5naWZ5KFxyXG4gICAgICAgICAgICAgIHBhc3NLZXlCdW5kbGUud3JhcHBlZFBhc3NJZHBWZXJpZmllclBya1xyXG4gICAgICAgICAgICApLFxyXG4gICAgICAgICAgICBwYXNzS2V5UGFyYW1zOiBKU09OLnN0cmluZ2lmeShwYXNzS2V5QnVuZGxlLnBhc3NLZXlQYXJhbXMpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9LFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB0b2tlbjogcmVzcG9uc2UucGFzc3dvcmRDaGFuZ2UudG9rZW4sXHJcbiAgICAgIG5ld1Bhc3NLZXlJZDogcmVzcG9uc2UucGFzc3dvcmRDaGFuZ2UubmV3UGFzc0tleS5pZCxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRDaGFuZ2VQYXNzd29yZENvbmZpZygpOiBQcm9taXNlPFBhc3N3b3JkQ2hhbmdlQ29uZmlnPiB7XHJcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmFwb2xsby5xdWVyeTxhbnk+KHtcclxuICAgICAgcXVlcnk6IFBhc3N3b3JkQ2hhbmdlQ29uZmlnUXVlcnksXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCByZXQgPSByZXMucGFzc3dvcmRDaGFuZ2VDb25maWcgYXMgUGFzc3dvcmRDaGFuZ2VDb25maWc7XHJcblxyXG4gICAgcmV0LmF1dGhUaW1lID0gbmV3IERhdGUocmV0LmF1dGhUaW1lKTtcclxuICAgIHJldC5zZXJ2ZXJUaW1lID0gbmV3IERhdGUocmV0LnNlcnZlclRpbWUpO1xyXG4gICAgcmV0dXJuIHJldDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBwYXNzd29yZFN0cmVuZ3RoKHBhc3N3b3JkKTogeyB5ZWFyczogbnVtYmVyOyBiaXRzOiBudW1iZXIgfSB7XHJcbiAgICBjb25zdCB1cHBlciA9IC9bQS1aXS9nO1xyXG4gICAgY29uc3QgbG93ZXIgPSAvW2Etel0vZztcclxuICAgIGNvbnN0IGRpZ2l0ID0gL1swLTldL2c7XHJcblxyXG4gICAgY29uc3QgdXBwZXJDaG9pY2VzID0gMjY7XHJcbiAgICBjb25zdCBsb3dlckNob2ljZXMgPSAyNjtcclxuICAgIGNvbnN0IGRpZ2l0Q2hvaWNlcyA9IDEwO1xyXG4gICAgY29uc3Qgc3BlY2lhbENob2ljZXMgPSAzMDsgLy8gL1shXCIjJCUmJygpKissLS4vOjs8PT4/QFtcXF1eX2B7fH1+XS9nXHJcblxyXG4gICAgZnVuY3Rpb24gaW5zdGFuY2VDb3VudChzdHIsIHJlKSB7XHJcbiAgICAgIHJldHVybiAoKHN0ciB8fCAnJykubWF0Y2gocmUpIHx8IFtdKS5sZW5ndGg7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgdXBwZXJzID0gaW5zdGFuY2VDb3VudChwYXNzd29yZCwgdXBwZXIpO1xyXG4gICAgY29uc3QgbG93ZXJzID0gaW5zdGFuY2VDb3VudChwYXNzd29yZCwgbG93ZXIpO1xyXG4gICAgY29uc3QgZGlnaXRzID0gaW5zdGFuY2VDb3VudChwYXNzd29yZCwgZGlnaXQpO1xyXG4gICAgY29uc3Qgc3BlY2lhbHMgPSBwYXNzd29yZC5sZW5ndGggLSB1cHBlcnMgLSBsb3dlcnMgLSBkaWdpdHM7XHJcblxyXG4gICAgbGV0IGNob2ljZXMgPSAwO1xyXG4gICAgaWYgKHVwcGVycykge1xyXG4gICAgICBjaG9pY2VzICs9IHVwcGVyQ2hvaWNlcztcclxuICAgIH1cclxuICAgIGlmIChsb3dlcnMpIHtcclxuICAgICAgY2hvaWNlcyArPSBsb3dlckNob2ljZXM7XHJcbiAgICB9XHJcbiAgICBpZiAoZGlnaXRzKSB7XHJcbiAgICAgIGNob2ljZXMgKz0gZGlnaXRDaG9pY2VzO1xyXG4gICAgfVxyXG4gICAgaWYgKHNwZWNpYWxzKSB7XHJcbiAgICAgIGNob2ljZXMgKz0gc3BlY2lhbENob2ljZXM7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHBhc3N3b3JkLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHllYXJzOiAwLFxyXG4gICAgICAgIC8vIGJpdHMgb2YgZW50cm9weVxyXG4gICAgICAgIGJpdHM6IDAsXHJcbiAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgcGVybXV0YXRpb25zID0gTWF0aC5wb3coY2hvaWNlcywgcGFzc3dvcmQubGVuZ3RoKTtcclxuXHJcbiAgICBjb25zdCB5ZWFycyA9XHJcbiAgICAgICg1NDAwMCAqIHBlcm11dGF0aW9ucykgL1xyXG4gICAgICBNYXRoLnBvdyh1cHBlckNob2ljZXMgKyBsb3dlckNob2ljZXMgKyBkaWdpdENob2ljZXMsIDEyKTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIHllYXJzLFxyXG4gICAgICAvLyBiaXRzIG9mIGVudHJvcHlcclxuICAgICAgYml0czogTWF0aC5yb3VuZChNYXRoLmxvZzIocGVybXV0YXRpb25zKSksXHJcbiAgICB9O1xyXG4gIH1cclxufVxyXG4iXX0=
@@ -0,0 +1,172 @@
1
+ import { __awaiter } from "tslib";
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { Inject, Injectable } from '@angular/core';
4
+ import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
5
+ import { EncryptionService } from '../cryptography/encryption.service';
6
+ import { KeyFactoryService } from '../cryptography/key-factory.service';
7
+ import { LR_CONFIG } from '../life-ready.config';
8
+ import { PasswordService } from './password.service';
9
+ import * as i0 from "@angular/core";
10
+ import * as i1 from "../life-ready.config";
11
+ import * as i2 from "@aws-amplify/auth/lib-esm/Auth";
12
+ import * as i3 from "@angular/common/http";
13
+ import * as i4 from "../cryptography/key-factory.service";
14
+ import * as i5 from "../cryptography/encryption.service";
15
+ import * as i6 from "./password.service";
16
+ export class RegisterService {
17
+ constructor(config, auth, http, keyFactory, encryptionService, passwordService) {
18
+ this.config = config;
19
+ this.auth = auth;
20
+ this.http = http;
21
+ this.keyFactory = keyFactory;
22
+ this.encryptionService = encryptionService;
23
+ this.passwordService = passwordService;
24
+ }
25
+ /**
26
+ * Request a verification code to be sent out to an email.
27
+ * @return Info needed to be submitted along with the verification code
28
+ */
29
+ verifyEmail(email) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ const { claim_id } = yield this.http
32
+ .post(`${this.config.authUrl}cove/claim/email/`, {
33
+ address: email,
34
+ context: 'signup',
35
+ })
36
+ .toPromise();
37
+ return claim_id;
38
+ });
39
+ }
40
+ verifyPhone(phoneNumber) {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ const { claim_id } = yield this.http
43
+ .post(`${this.config.authUrl}cove/claim/sms/`, {
44
+ address: phoneNumber,
45
+ context: 'signup',
46
+ })
47
+ .toPromise();
48
+ return claim_id;
49
+ });
50
+ }
51
+ confirmVerificationCode(verificationId, verificationCode) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ const { token } = yield this.http
54
+ .post(`${this.config.authUrl}cove/respond/`, {
55
+ claim_id: verificationId,
56
+ v_code: verificationCode,
57
+ })
58
+ .toPromise();
59
+ return token;
60
+ });
61
+ }
62
+ register(email, password, verificationId, verificationToken, verificationType = 'email') {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ // Generate the key material needed for PassIdp which will be the password used for Cognito.
65
+ const passKeyBundle = yield this.passwordService.createPassKeyBundle(password);
66
+ const masterKey = yield this.keyFactory.createKey();
67
+ const wrappedMasterKey = yield this.encryptionService.encrypt(passKeyBundle.passKey, masterKey.toJSON(true));
68
+ const rootKey = yield this.keyFactory.createKey();
69
+ const wrappedRootKey = yield this.encryptionService.encrypt(masterKey, rootKey.toJSON(true));
70
+ // Encryption PKC key
71
+ const prk = yield this.keyFactory.createPkcKey();
72
+ const wrappedPrk = yield this.encryptionService.encrypt(rootKey, prk.toJSON(true));
73
+ // Signing PKC key
74
+ const sigPrk = yield this.keyFactory.createPkcSignKey();
75
+ const wrappedSigPrk = yield this.encryptionService.encrypt(rootKey, sigPrk.toJSON(true));
76
+ // API call to setup profile
77
+ const user = yield this.http
78
+ .post(`${this.config.authUrl}users/`, {
79
+ claims: [
80
+ {
81
+ type: verificationType,
82
+ token: verificationToken,
83
+ claim_id: verificationId,
84
+ },
85
+ ],
86
+ pass_idp_params: passKeyBundle.passIdpParams,
87
+ pass_idp_verifier_pbk: passKeyBundle.passIdpVerifier.toJSON(),
88
+ wrapped_pass_idp_verifier_prk: passKeyBundle.wrappedPassIdpVerifierPrk,
89
+ pass_key_params: passKeyBundle.passKeyParams,
90
+ wrapped_master_key: wrappedMasterKey,
91
+ wrapped_root_key: wrappedRootKey,
92
+ pbk: prk.toJSON(),
93
+ wrapped_prk: wrappedPrk,
94
+ sig_pbk: sigPrk.toJSON(),
95
+ wrapped_sig_prk: wrappedSigPrk,
96
+ })
97
+ .toPromise();
98
+ // API call to create user on cognito
99
+ const attributes = {};
100
+ user.claims.forEach((claim) => {
101
+ attributes[claim.type] = claim.value;
102
+ });
103
+ // Random suffix for uniqueness. If there's a duplicate, then used just needs to
104
+ // sign up again. But chances of collision is low.
105
+ const suffix = this.keyFactory.randomDigitsNoZeros(4);
106
+ const cognitoUser = yield this.auth.signUp({
107
+ username: `${email.split('@')[0]}.${suffix}`,
108
+ password: this.passwordService.getPassIdpString(passKeyBundle.passIdp),
109
+ attributes,
110
+ // Unfortunately, validationData is not passed to the post
111
+ // confirmation cognito trigger. So can can't do the association there.
112
+ // The current workflow will create a new user on LR before signing up
113
+ // with Cognito. Then Cognito can use the user.id and user.pre_sign_up_token to
114
+ // do the validation of the attributes.
115
+ // validationData: [
116
+ // new CognitoUserAttribute({
117
+ // Name: "user_id",
118
+ // Value: String(user.id)
119
+ // }),
120
+ // new CognitoUserAttribute({
121
+ // Name: "user_pre_sign_up_token",
122
+ // Value: user.pre_sign_up_token
123
+ // })
124
+ // ]
125
+ clientMetadata: {
126
+ user_id: String(user.id),
127
+ user_pre_sign_up_token: String(user.pre_sign_up_token),
128
+ },
129
+ });
130
+ return {
131
+ username: cognitoUser.user.getUsername(),
132
+ userId: user.id,
133
+ preSignUpToken: user.pre_sign_up_token,
134
+ userSub: cognitoUser.userSub,
135
+ };
136
+ });
137
+ }
138
+ hibpBreachedAccounts(account) {
139
+ return __awaiter(this, void 0, void 0, function* () {
140
+ // The account is just the email
141
+ try {
142
+ const response = yield this.http
143
+ .get(`${this.config.authUrl}users/hibp/breachedaccount/${account}/?truncateResponse=false`)
144
+ .toPromise();
145
+ return response;
146
+ }
147
+ catch (error) {
148
+ if (error.status === 404) {
149
+ return null;
150
+ }
151
+ else {
152
+ throw error;
153
+ }
154
+ }
155
+ });
156
+ }
157
+ }
158
+ RegisterService.ɵprov = i0.ɵɵdefineInjectable({ factory: function RegisterService_Factory() { return new RegisterService(i0.ɵɵinject(i1.LR_CONFIG), i0.ɵɵinject(i2.AuthClass), i0.ɵɵinject(i3.HttpClient), i0.ɵɵinject(i4.KeyFactoryService), i0.ɵɵinject(i5.EncryptionService), i0.ɵɵinject(i6.PasswordService)); }, token: RegisterService, providedIn: "root" });
159
+ RegisterService.decorators = [
160
+ { type: Injectable, args: [{
161
+ providedIn: 'root',
162
+ },] }
163
+ ];
164
+ RegisterService.ctorParameters = () => [
165
+ { type: undefined, decorators: [{ type: Inject, args: [LR_CONFIG,] }] },
166
+ { type: AuthClass },
167
+ { type: HttpClient },
168
+ { type: KeyFactoryService },
169
+ { type: EncryptionService },
170
+ { type: PasswordService }
171
+ ];
172
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJDOi9Qcm9qZWN0cy90ZXN0L3Byb2plY3RzL2NvcmUvc3JjLyIsInNvdXJjZXMiOlsibGliL2F1dGgvcmVnaXN0ZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUMzRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN2RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUN4RSxPQUFPLEVBQW1CLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7Ozs7Ozs7QUFNckQsTUFBTSxPQUFPLGVBQWU7SUFDMUIsWUFDNkIsTUFBdUIsRUFDMUMsSUFBZSxFQUNmLElBQWdCLEVBQ2hCLFVBQTZCLEVBQzdCLGlCQUFvQyxFQUNwQyxlQUFnQztRQUxiLFdBQU0sR0FBTixNQUFNLENBQWlCO1FBQzFDLFNBQUksR0FBSixJQUFJLENBQVc7UUFDZixTQUFJLEdBQUosSUFBSSxDQUFZO1FBQ2hCLGVBQVUsR0FBVixVQUFVLENBQW1CO1FBQzdCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsb0JBQWUsR0FBZixlQUFlLENBQWlCO0lBQ3ZDLENBQUM7SUFFSjs7O09BR0c7SUFDVSxXQUFXLENBQUMsS0FBYTs7WUFDcEMsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUk7aUJBQ2pDLElBQUksQ0FBZSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxtQkFBbUIsRUFBRTtnQkFD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bW1vbi9odHRwJztcclxuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEF1dGhDbGFzcyB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9hdXRoL2xpYi1lc20vQXV0aCc7XHJcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2VuY3J5cHRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IEtleUZhY3RvcnlTZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2tleS1mYWN0b3J5LnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBMaWZlUmVhZHlDb25maWcsIExSX0NPTkZJRyB9IGZyb20gJy4uL2xpZmUtcmVhZHkuY29uZmlnJztcclxuaW1wb3J0IHsgUGFzc3dvcmRTZXJ2aWNlIH0gZnJvbSAnLi9wYXNzd29yZC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUmVnaXN0ZXJSZXN1bHQgfSBmcm9tICcuL2F1dGgudHlwZXMnO1xyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290JyxcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlZ2lzdGVyU2VydmljZSB7XHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0KExSX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IExpZmVSZWFkeUNvbmZpZyxcclxuICAgIHByaXZhdGUgYXV0aDogQXV0aENsYXNzLFxyXG4gICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxyXG4gICAgcHJpdmF0ZSBrZXlGYWN0b3J5OiBLZXlGYWN0b3J5U2VydmljZSxcclxuICAgIHByaXZhdGUgZW5jcnlwdGlvblNlcnZpY2U6IEVuY3J5cHRpb25TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBwYXNzd29yZFNlcnZpY2U6IFBhc3N3b3JkU2VydmljZVxyXG4gICkge31cclxuXHJcbiAgLyoqXHJcbiAgICogUmVxdWVzdCBhIHZlcmlmaWNhdGlvbiBjb2RlIHRvIGJlIHNlbnQgb3V0IHRvIGFuIGVtYWlsLlxyXG4gICAqIEByZXR1cm4gSW5mbyBuZWVkZWQgdG8gYmUgc3VibWl0dGVkIGFsb25nIHdpdGggdGhlIHZlcmlmaWNhdGlvbiBjb2RlXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIHZlcmlmeUVtYWlsKGVtYWlsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgeyBjbGFpbV9pZCB9ID0gYXdhaXQgdGhpcy5odHRwXHJcbiAgICAgIC5wb3N0PHsgY2xhaW1faWQgfT4oYCR7dGhpcy5jb25maWcuYXV0aFVybH1jb3ZlL2NsYWltL2VtYWlsL2AsIHtcclxuICAgICAgICBhZGRyZXNzOiBlbWFpbCxcclxuICAgICAgICBjb250ZXh0OiAnc2lnbnVwJyxcclxuICAgICAgfSlcclxuICAgICAgLnRvUHJvbWlzZSgpO1xyXG4gICAgcmV0dXJuIGNsYWltX2lkO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIHZlcmlmeVBob25lKHBob25lTnVtYmVyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgeyBjbGFpbV9pZCB9ID0gYXdhaXQgdGhpcy5odHRwXHJcbiAgICAgIC5wb3N0PHsgY2xhaW1faWQgfT4oYCR7dGhpcy5jb25maWcuYXV0aFVybH1jb3ZlL2NsYWltL3Ntcy9gLCB7XHJcbiAgICAgICAgYWRkcmVzczogcGhvbmVOdW1iZXIsXHJcbiAgICAgICAgY29udGV4dDogJ3NpZ251cCcsXHJcbiAgICAgIH0pXHJcbiAgICAgIC50b1Byb21pc2UoKTtcclxuICAgIHJldHVybiBjbGFpbV9pZDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBjb25maXJtVmVyaWZpY2F0aW9uQ29kZShcclxuICAgIHZlcmlmaWNhdGlvbklkOiBzdHJpbmcsXHJcbiAgICB2ZXJpZmljYXRpb25Db2RlOiBzdHJpbmdcclxuICApOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgeyB0b2tlbiB9ID0gYXdhaXQgdGhpcy5odHRwXHJcbiAgICAgIC5wb3N0PHsgdG9rZW4gfT4oYCR7dGhpcy5jb25maWcuYXV0aFVybH1jb3ZlL3Jlc3BvbmQvYCwge1xyXG4gICAgICAgIGNsYWltX2lkOiB2ZXJpZmljYXRpb25JZCxcclxuICAgICAgICB2X2NvZGU6IHZlcmlmaWNhdGlvbkNvZGUsXHJcbiAgICAgIH0pXHJcbiAgICAgIC50b1Byb21pc2UoKTtcclxuICAgIHJldHVybiB0b2tlbjtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyByZWdpc3RlcihcclxuICAgIGVtYWlsOiBzdHJpbmcsXHJcbiAgICBwYXNzd29yZDogc3RyaW5nLFxyXG4gICAgdmVyaWZpY2F0aW9uSWQ6IHN0cmluZyxcclxuICAgIHZlcmlmaWNhdGlvblRva2VuOiBzdHJpbmcsXHJcbiAgICB2ZXJpZmljYXRpb25UeXBlOiAnZW1haWwnIHwgJ3Bob25lJyA9ICdlbWFpbCdcclxuICApOiBQcm9taXNlPFJlZ2lzdGVyUmVzdWx0PiB7XHJcbiAgICAvLyBHZW5lcmF0ZSB0aGUga2V5IG1hdGVyaWFsIG5lZWRlZCBmb3IgUGFzc0lkcCB3aGljaCB3aWxsIGJlIHRoZSBwYXNzd29yZCB1c2VkIGZvciBDb2duaXRvLlxyXG4gICAgY29uc3QgcGFzc0tleUJ1bmRsZSA9IGF3YWl0IHRoaXMucGFzc3dvcmRTZXJ2aWNlLmNyZWF0ZVBhc3NLZXlCdW5kbGUoXHJcbiAgICAgIHBhc3N3b3JkXHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IG1hc3RlcktleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVLZXkoKTtcclxuICAgIGNvbnN0IHdyYXBwZWRNYXN0ZXJLZXkgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXHJcbiAgICAgIHBhc3NLZXlCdW5kbGUucGFzc0tleSxcclxuICAgICAgbWFzdGVyS2V5LnRvSlNPTih0cnVlKVxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCByb290S2V5ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZUtleSgpO1xyXG4gICAgY29uc3Qgd3JhcHBlZFJvb3RLZXkgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXHJcbiAgICAgIG1hc3RlcktleSxcclxuICAgICAgcm9vdEtleS50b0pTT04odHJ1ZSlcclxuICAgICk7XHJcblxyXG4gICAgLy8gRW5jcnlwdGlvbiBQS0Mga2V5XHJcbiAgICBjb25zdCBwcmsgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlUGtjS2V5KCk7XHJcbiAgICBjb25zdCB3cmFwcGVkUHJrID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KFxyXG4gICAgICByb290S2V5LFxyXG4gICAgICBwcmsudG9KU09OKHRydWUpXHJcbiAgICApO1xyXG5cclxuICAgIC8vIFNpZ25pbmcgUEtDIGtleVxyXG4gICAgY29uc3Qgc2lnUHJrID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZVBrY1NpZ25LZXkoKTtcclxuICAgIGNvbnN0IHdyYXBwZWRTaWdQcmsgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXHJcbiAgICAgIHJvb3RLZXksXHJcbiAgICAgIHNpZ1Byay50b0pTT04odHJ1ZSlcclxuICAgICk7XHJcblxyXG4gICAgLy8gQVBJIGNhbGwgdG8gc2V0dXAgcHJvZmlsZVxyXG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuaHR0cFxyXG4gICAgICAucG9zdDxhbnk+KGAke3RoaXMuY29uZmlnLmF1dGhVcmx9dXNlcnMvYCwge1xyXG4gICAgICAgIGNsYWltczogW1xyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICB0eXBlOiB2ZXJpZmljYXRpb25UeXBlLFxyXG4gICAgICAgICAgICB0b2tlbjogdmVyaWZpY2F0aW9uVG9rZW4sXHJcbiAgICAgICAgICAgIGNsYWltX2lkOiB2ZXJpZmljYXRpb25JZCxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgXSxcclxuICAgICAgICBwYXNzX2lkcF9wYXJhbXM6IHBhc3NLZXlCdW5kbGUucGFzc0lkcFBhcmFtcyxcclxuICAgICAgICBwYXNzX2lkcF92ZXJpZmllcl9wYms6IHBhc3NLZXlCdW5kbGUucGFzc0lkcFZlcmlmaWVyLnRvSlNPTigpLFxyXG4gICAgICAgIHdyYXBwZWRfcGFzc19pZHBfdmVyaWZpZXJfcHJrOiBwYXNzS2V5QnVuZGxlLndyYXBwZWRQYXNzSWRwVmVyaWZpZXJQcmssXHJcbiAgICAgICAgcGFzc19rZXlfcGFyYW1zOiBwYXNzS2V5QnVuZGxlLnBhc3NLZXlQYXJhbXMsXHJcbiAgICAgICAgd3JhcHBlZF9tYXN0ZXJfa2V5OiB3cmFwcGVkTWFzdGVyS2V5LFxyXG4gICAgICAgIHdyYXBwZWRfcm9vdF9rZXk6IHdyYXBwZWRSb290S2V5LFxyXG4gICAgICAgIHBiazogcHJrLnRvSlNPTigpLCAvLyBwdWJsaWMgZW5jcnlwdGlvbiBrZXlcclxuICAgICAgICB3cmFwcGVkX3Byazogd3JhcHBlZFByayxcclxuICAgICAgICBzaWdfcGJrOiBzaWdQcmsudG9KU09OKCksIC8vIHB1YmxpYyBzaWduaW5nIGtleVxyXG4gICAgICAgIHdyYXBwZWRfc2lnX3Byazogd3JhcHBlZFNpZ1ByayxcclxuICAgICAgfSlcclxuICAgICAgLnRvUHJvbWlzZSgpO1xyXG5cclxuICAgIC8vIEFQSSBjYWxsIHRvIGNyZWF0ZSB1c2VyIG9uIGNvZ25pdG9cclxuICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7fTtcclxuICAgIHVzZXIuY2xhaW1zLmZvckVhY2goKGNsYWltKSA9PiB7XHJcbiAgICAgIGF0dHJpYnV0ZXNbY2xhaW0udHlwZV0gPSBjbGFpbS52YWx1ZTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFJhbmRvbSBzdWZmaXggZm9yIHVuaXF1ZW5lc3MuIElmIHRoZXJlJ3MgYSBkdXBsaWNhdGUsIHRoZW4gdXNlZCBqdXN0IG5lZWRzIHRvXHJcbiAgICAvLyBzaWduIHVwIGFnYWluLiBCdXQgY2hhbmNlcyBvZiBjb2xsaXNpb24gaXMgbG93LlxyXG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5rZXlGYWN0b3J5LnJhbmRvbURpZ2l0c05vWmVyb3MoNCk7XHJcblxyXG4gICAgY29uc3QgY29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguc2lnblVwKHtcclxuICAgICAgdXNlcm5hbWU6IGAke2VtYWlsLnNwbGl0KCdAJylbMF19LiR7c3VmZml4fWAsXHJcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkU2VydmljZS5nZXRQYXNzSWRwU3RyaW5nKHBhc3NLZXlCdW5kbGUucGFzc0lkcCksXHJcbiAgICAgIGF0dHJpYnV0ZXMsXHJcbiAgICAgIC8vIFVuZm9ydHVuYXRlbHksIHZhbGlkYXRpb25EYXRhIGlzIG5vdCBwYXNzZWQgdG8gdGhlIHBvc3RcclxuICAgICAgLy8gY29uZmlybWF0aW9uIGNvZ25pdG8gdHJpZ2dlci4gU28gY2FuIGNhbid0IGRvIHRoZSBhc3NvY2lhdGlvbiB0aGVyZS5cclxuICAgICAgLy8gVGhlIGN1cnJlbnQgd29ya2Zsb3cgd2lsbCBjcmVhdGUgYSBuZXcgdXNlciBvbiBMUiBiZWZvcmUgc2lnbmluZyB1cFxyXG4gICAgICAvLyB3aXRoIENvZ25pdG8uIFRoZW4gQ29nbml0byBjYW4gdXNlIHRoZSB1c2VyLmlkIGFuZCB1c2VyLnByZV9zaWduX3VwX3Rva2VuIHRvXHJcbiAgICAgIC8vIGRvIHRoZSB2YWxpZGF0aW9uIG9mIHRoZSBhdHRyaWJ1dGVzLlxyXG4gICAgICAvLyB2YWxpZGF0aW9uRGF0YTogW1xyXG4gICAgICAvLyAgIG5ldyBDb2duaXRvVXNlckF0dHJpYnV0ZSh7XHJcbiAgICAgIC8vICAgICBOYW1lOiBcInVzZXJfaWRcIixcclxuICAgICAgLy8gICAgIFZhbHVlOiBTdHJpbmcodXNlci5pZClcclxuICAgICAgLy8gICB9KSxcclxuICAgICAgLy8gICBuZXcgQ29nbml0b1VzZXJBdHRyaWJ1dGUoe1xyXG4gICAgICAvLyAgICAgTmFtZTogXCJ1c2VyX3ByZV9zaWduX3VwX3Rva2VuXCIsXHJcbiAgICAgIC8vICAgICBWYWx1ZTogdXNlci5wcmVfc2lnbl91cF90b2tlblxyXG4gICAgICAvLyAgIH0pXHJcbiAgICAgIC8vIF1cclxuICAgICAgY2xpZW50TWV0YWRhdGE6IHtcclxuICAgICAgICB1c2VyX2lkOiBTdHJpbmcodXNlci5pZCksXHJcbiAgICAgICAgdXNlcl9wcmVfc2lnbl91cF90b2tlbjogU3RyaW5nKHVzZXIucHJlX3NpZ25fdXBfdG9rZW4pLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgdXNlcm5hbWU6IGNvZ25pdG9Vc2VyLnVzZXIuZ2V0VXNlcm5hbWUoKSxcclxuICAgICAgdXNlcklkOiB1c2VyLmlkLFxyXG4gICAgICBwcmVTaWduVXBUb2tlbjogdXNlci5wcmVfc2lnbl91cF90b2tlbixcclxuICAgICAgdXNlclN1YjogY29nbml0b1VzZXIudXNlclN1YixcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgaGlicEJyZWFjaGVkQWNjb3VudHMoYWNjb3VudDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIC8vIFRoZSBhY2NvdW50IGlzIGp1c3QgdGhlIGVtYWlsXHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuaHR0cFxyXG4gICAgICAgIC5nZXQoXHJcbiAgICAgICAgICBgJHt0aGlzLmNvbmZpZy5hdXRoVXJsfXVzZXJzL2hpYnAvYnJlYWNoZWRhY2NvdW50LyR7YWNjb3VudH0vP3RydW5jYXRlUmVzcG9uc2U9ZmFsc2VgXHJcbiAgICAgICAgKVxyXG4gICAgICAgIC50b1Byb21pc2UoKTtcclxuICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDA0KSB7XHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19