@azure/msal-node-extensions 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (47) hide show
  1. package/README.md +156 -5
  2. package/binding.gyp +11 -1
  3. package/dist/{dpapi-addon/Dpapi.d.ts → Dpapi.d.ts} +0 -0
  4. package/dist/error/PersistenceError.d.ts +28 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/msal-node-extensions.cjs.development.js +603 -859
  7. package/dist/msal-node-extensions.cjs.development.js.map +1 -1
  8. package/dist/msal-node-extensions.cjs.production.min.js +1 -1
  9. package/dist/msal-node-extensions.cjs.production.min.js.map +1 -1
  10. package/dist/msal-node-extensions.esm.js +613 -874
  11. package/dist/msal-node-extensions.esm.js.map +1 -1
  12. package/dist/packageMetadata.d.ts +2 -0
  13. package/dist/persistence/BasePersistence.d.ts +5 -0
  14. package/dist/persistence/FilePersistence.d.ts +4 -2
  15. package/dist/persistence/FilePersistenceWithDataProtection.d.ts +3 -1
  16. package/dist/persistence/IPersistence.d.ts +3 -1
  17. package/dist/persistence/IPersistenceConfiguration.d.ts +10 -0
  18. package/dist/persistence/KeychainPersistence.d.ts +3 -1
  19. package/dist/persistence/LibSecretPersistence.d.ts +3 -1
  20. package/dist/persistence/PersistenceCachePlugin.d.ts +11 -7
  21. package/dist/persistence/PersistenceCreator.d.ts +5 -0
  22. package/dist/utils/Constants.d.ts +26 -0
  23. package/dist/utils/Environment.d.ts +16 -0
  24. package/package.json +27 -15
  25. package/src/{dpapi-addon/Dpapi.ts → Dpapi.ts} +12 -12
  26. package/src/dpapi-addon/dpapi_addon.h +2 -1
  27. package/src/dpapi-addon/dpapi_not_supported.cpp +4 -10
  28. package/src/dpapi-addon/dpapi_win.cpp +25 -33
  29. package/src/dpapi-addon/main.cpp +14 -16
  30. package/src/error/PersistenceError.ts +101 -61
  31. package/src/index.ts +16 -8
  32. package/src/lock/CrossPlatformLock.ts +89 -89
  33. package/src/lock/CrossPlatformLockOptions.ts +15 -15
  34. package/src/packageMetadata.ts +3 -0
  35. package/src/persistence/BasePersistence.ts +43 -0
  36. package/src/persistence/FilePersistence.ts +140 -134
  37. package/src/persistence/FilePersistenceWithDataProtection.ts +92 -84
  38. package/src/persistence/IPersistence.ts +4 -2
  39. package/src/persistence/IPersistenceConfiguration.ts +17 -0
  40. package/src/persistence/KeychainPersistence.ts +89 -78
  41. package/src/persistence/LibSecretPersistence.ts +90 -79
  42. package/src/persistence/PersistenceCachePlugin.ts +40 -30
  43. package/src/persistence/PersistenceCreator.ts +78 -0
  44. package/src/utils/Constants.ts +62 -30
  45. package/src/utils/Environment.ts +101 -0
  46. package/CHANGELOG.json +0 -50
  47. package/changelog.md +0 -28
@@ -1,200 +1,14 @@
1
1
  import { promises } from 'fs';
2
2
  import { pid } from 'process';
3
- import { dirname } from 'path';
4
- import { Logger, LogLevel } from '@azure/msal-common';
3
+ import path, { dirname } from 'path';
4
+ import { Logger, LogLevel, StringUtils } from '@azure/msal-common';
5
5
  import { setPassword, getPassword, deletePassword } from 'keytar';
6
6
 
7
- // A type of promise-like that resolves synchronously and supports only one observer
8
- const _Pact = /*#__PURE__*/(function() {
9
- function _Pact() {}
10
- _Pact.prototype.then = function(onFulfilled, onRejected) {
11
- const result = new _Pact();
12
- const state = this.s;
13
- if (state) {
14
- const callback = state & 1 ? onFulfilled : onRejected;
15
- if (callback) {
16
- try {
17
- _settle(result, 1, callback(this.v));
18
- } catch (e) {
19
- _settle(result, 2, e);
20
- }
21
- return result;
22
- } else {
23
- return this;
24
- }
25
- }
26
- this.o = function(_this) {
27
- try {
28
- const value = _this.v;
29
- if (_this.s & 1) {
30
- _settle(result, 1, onFulfilled ? onFulfilled(value) : value);
31
- } else if (onRejected) {
32
- _settle(result, 1, onRejected(value));
33
- } else {
34
- _settle(result, 2, value);
35
- }
36
- } catch (e) {
37
- _settle(result, 2, e);
38
- }
39
- };
40
- return result;
41
- };
42
- return _Pact;
43
- })();
44
-
45
- // Settles a pact synchronously
46
- function _settle(pact, state, value) {
47
- if (!pact.s) {
48
- if (value instanceof _Pact) {
49
- if (value.s) {
50
- if (state & 1) {
51
- state = value.s;
52
- }
53
- value = value.v;
54
- } else {
55
- value.o = _settle.bind(null, pact, state);
56
- return;
57
- }
58
- }
59
- if (value && value.then) {
60
- value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));
61
- return;
62
- }
63
- pact.s = state;
64
- pact.v = value;
65
- const observer = pact.o;
66
- if (observer) {
67
- observer(pact);
68
- }
69
- }
70
- }
71
-
72
- function _isSettledPact(thenable) {
73
- return thenable instanceof _Pact && thenable.s & 1;
74
- }
75
-
76
- const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";
77
-
78
- const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";
79
-
80
- // Asynchronously implement a generic for loop
81
- function _for(test, update, body) {
82
- var stage;
83
- for (;;) {
84
- var shouldContinue = test();
85
- if (_isSettledPact(shouldContinue)) {
86
- shouldContinue = shouldContinue.v;
87
- }
88
- if (!shouldContinue) {
89
- return result;
90
- }
91
- if (shouldContinue.then) {
92
- stage = 0;
93
- break;
94
- }
95
- var result = body();
96
- if (result && result.then) {
97
- if (_isSettledPact(result)) {
98
- result = result.s;
99
- } else {
100
- stage = 1;
101
- break;
102
- }
103
- }
104
- if (update) {
105
- var updateValue = update();
106
- if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
107
- stage = 2;
108
- break;
109
- }
110
- }
111
- }
112
- var pact = new _Pact();
113
- var reject = _settle.bind(null, pact, 2);
114
- (stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
115
- return pact;
116
- function _resumeAfterBody(value) {
117
- result = value;
118
- do {
119
- if (update) {
120
- updateValue = update();
121
- if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
122
- updateValue.then(_resumeAfterUpdate).then(void 0, reject);
123
- return;
124
- }
125
- }
126
- shouldContinue = test();
127
- if (!shouldContinue || (_isSettledPact(shouldContinue) && !shouldContinue.v)) {
128
- _settle(pact, 1, result);
129
- return;
130
- }
131
- if (shouldContinue.then) {
132
- shouldContinue.then(_resumeAfterTest).then(void 0, reject);
133
- return;
134
- }
135
- result = body();
136
- if (_isSettledPact(result)) {
137
- result = result.v;
138
- }
139
- } while (!result || !result.then);
140
- result.then(_resumeAfterBody).then(void 0, reject);
141
- }
142
- function _resumeAfterTest(shouldContinue) {
143
- if (shouldContinue) {
144
- result = body();
145
- if (result && result.then) {
146
- result.then(_resumeAfterBody).then(void 0, reject);
147
- } else {
148
- _resumeAfterBody(result);
149
- }
150
- } else {
151
- _settle(pact, 1, result);
152
- }
153
- }
154
- function _resumeAfterUpdate() {
155
- if (shouldContinue = test()) {
156
- if (shouldContinue.then) {
157
- shouldContinue.then(_resumeAfterTest).then(void 0, reject);
158
- } else {
159
- _resumeAfterTest(shouldContinue);
160
- }
161
- } else {
162
- _settle(pact, 1, result);
163
- }
164
- }
165
- }
166
-
167
- // Asynchronously call a function and send errors to recovery continuation
168
- function _catch(body, recover) {
169
- try {
170
- var result = body();
171
- } catch(e) {
172
- return recover(e);
173
- }
174
- if (result && result.then) {
175
- return result.then(void 0, recover);
176
- }
177
- return result;
178
- }
179
-
180
- // Asynchronously await a promise and pass the result to a finally continuation
181
- function _finallyRethrows(body, finalizer) {
182
- try {
183
- var result = body();
184
- } catch (e) {
185
- return finalizer(true, e);
186
- }
187
- if (result && result.then) {
188
- return result.then(finalizer.bind(null, false), finalizer.bind(null, true));
189
- }
190
- return finalizer(false, result);
191
- }
192
-
193
7
  /*
194
8
  * Copyright (c) Microsoft Corporation. All rights reserved.
195
9
  * Licensed under the MIT License.
196
10
  */
197
- var Constants = {
11
+ const Constants = {
198
12
  /**
199
13
  * An existing file was the target of an operation that required that the target not exist
200
14
  */
@@ -216,106 +30,40 @@ var Constants = {
216
30
  /**
217
31
  * Default service name for using MSAL Keytar
218
32
  */
219
- DEFAULT_SERVICE_NAME: "msal-node-extensions"
220
- };
221
-
222
- function _inheritsLoose(subClass, superClass) {
223
- subClass.prototype = Object.create(superClass.prototype);
224
- subClass.prototype.constructor = subClass;
225
- subClass.__proto__ = superClass;
226
- }
33
+ DEFAULT_SERVICE_NAME: "msal-node-extensions",
227
34
 
228
- function _getPrototypeOf(o) {
229
- _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
230
- return o.__proto__ || Object.getPrototypeOf(o);
231
- };
232
- return _getPrototypeOf(o);
233
- }
234
-
235
- function _setPrototypeOf(o, p) {
236
- _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
237
- o.__proto__ = p;
238
- return o;
239
- };
240
-
241
- return _setPrototypeOf(o, p);
242
- }
243
-
244
- function _isNativeReflectConstruct() {
245
- if (typeof Reflect === "undefined" || !Reflect.construct) return false;
246
- if (Reflect.construct.sham) return false;
247
- if (typeof Proxy === "function") return true;
248
-
249
- try {
250
- Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
251
- return true;
252
- } catch (e) {
253
- return false;
254
- }
255
- }
256
-
257
- function _construct(Parent, args, Class) {
258
- if (_isNativeReflectConstruct()) {
259
- _construct = Reflect.construct;
260
- } else {
261
- _construct = function _construct(Parent, args, Class) {
262
- var a = [null];
263
- a.push.apply(a, args);
264
- var Constructor = Function.bind.apply(Parent, a);
265
- var instance = new Constructor();
266
- if (Class) _setPrototypeOf(instance, Class.prototype);
267
- return instance;
268
- };
269
- }
270
-
271
- return _construct.apply(null, arguments);
272
- }
273
-
274
- function _isNativeFunction(fn) {
275
- return Function.toString.call(fn).indexOf("[native code]") !== -1;
276
- }
277
-
278
- function _wrapNativeSuper(Class) {
279
- var _cache = typeof Map === "function" ? new Map() : undefined;
280
-
281
- _wrapNativeSuper = function _wrapNativeSuper(Class) {
282
- if (Class === null || !_isNativeFunction(Class)) return Class;
283
-
284
- if (typeof Class !== "function") {
285
- throw new TypeError("Super expression must either be null or a function");
286
- }
287
-
288
- if (typeof _cache !== "undefined") {
289
- if (_cache.has(Class)) return _cache.get(Class);
290
-
291
- _cache.set(Class, Wrapper);
292
- }
293
-
294
- function Wrapper() {
295
- return _construct(Class, arguments, _getPrototypeOf(this).constructor);
296
- }
297
-
298
- Wrapper.prototype = Object.create(Class.prototype, {
299
- constructor: {
300
- value: Wrapper,
301
- enumerable: false,
302
- writable: true,
303
- configurable: true
304
- }
305
- });
306
- return _setPrototypeOf(Wrapper, Class);
307
- };
35
+ /**
36
+ * Test data used to verify underlying persistence mechanism
37
+ */
38
+ PERSISTENCE_TEST_DATA: "Dummy data to verify underlying persistence mechanism",
308
39
 
309
- return _wrapNativeSuper(Class);
310
- }
40
+ /**
41
+ * This is the value of a the guid if the process is being ran by the root user
42
+ */
43
+ LINUX_ROOT_USER_GUID: 0,
311
44
 
312
- function _assertThisInitialized(self) {
313
- if (self === void 0) {
314
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
315
- }
45
+ /**
46
+ * List of environment variables
47
+ */
48
+ ENVIRONMENT: {
49
+ HOME: "HOME",
50
+ LOGNAME: "LOGNAME",
51
+ USER: "USER",
52
+ LNAME: "LNAME",
53
+ USERNAME: "USERNAME",
54
+ PLATFORM: "platform",
55
+ LOCAL_APPLICATION_DATA: "LOCALAPPDATA"
56
+ },
57
+ // Name of the default cache file
58
+ DEFAULT_CACHE_FILE_NAME: "cache.json"
59
+ };
60
+ var Platform;
316
61
 
317
- return self;
318
- }
62
+ (function (Platform) {
63
+ Platform["WINDOWS"] = "win32";
64
+ Platform["LINUX"] = "linux";
65
+ Platform["MACOS"] = "darwin";
66
+ })(Platform || (Platform = {}));
319
67
 
320
68
  /*
321
69
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -325,71 +73,113 @@ function _assertThisInitialized(self) {
325
73
  /**
326
74
  * Error thrown when trying to write MSAL cache to persistence.
327
75
  */
328
- var PersistenceError = /*#__PURE__*/function (_Error) {
329
- _inheritsLoose(PersistenceError, _Error);
330
-
331
- function PersistenceError(errorCode, errorMessage) {
332
- var _this;
333
-
334
- var errorString = errorMessage ? errorCode + ": " + errorMessage : errorCode;
335
- _this = _Error.call(this, errorString) || this;
336
- Object.setPrototypeOf(_assertThisInitialized(_this), PersistenceError.prototype);
337
- _this.errorCode = errorCode;
338
- _this.errorMessage = errorMessage;
339
- _this.name = "PersistenceError";
340
- return _this;
76
+ class PersistenceError extends Error {
77
+ constructor(errorCode, errorMessage) {
78
+ const errorString = errorMessage ? `${errorCode}: ${errorMessage}` : errorCode;
79
+ super(errorString);
80
+ Object.setPrototypeOf(this, PersistenceError.prototype);
81
+ this.errorCode = errorCode;
82
+ this.errorMessage = errorMessage;
83
+ this.name = "PersistenceError";
341
84
  }
342
85
  /**
343
86
  * Error thrown when trying to access the file system.
344
87
  */
345
88
 
346
89
 
347
- PersistenceError.createFileSystemError = function createFileSystemError(errorCode, errorMessage) {
90
+ static createFileSystemError(errorCode, errorMessage) {
348
91
  return new PersistenceError(errorCode, errorMessage);
349
92
  }
350
93
  /**
351
94
  * Error thrown when trying to write, load, or delete data from secret service on linux.
352
95
  * Libsecret is used to access secret service.
353
96
  */
354
- ;
355
97
 
356
- PersistenceError.createLibSecretError = function createLibSecretError(errorMessage) {
98
+
99
+ static createLibSecretError(errorMessage) {
357
100
  return new PersistenceError("GnomeKeyringError", errorMessage);
358
101
  }
359
102
  /**
360
103
  * Error thrown when trying to write, load, or delete data from keychain on macOs.
361
104
  */
362
- ;
363
105
 
364
- PersistenceError.createKeychainPersistenceError = function createKeychainPersistenceError(errorMessage) {
106
+
107
+ static createKeychainPersistenceError(errorMessage) {
365
108
  return new PersistenceError("KeychainError", errorMessage);
366
109
  }
367
110
  /**
368
111
  * Error thrown when trying to encrypt or decrypt data using DPAPI on Windows.
369
112
  */
370
- ;
371
113
 
372
- PersistenceError.createFilePersistenceWithDPAPIError = function createFilePersistenceWithDPAPIError(errorMessage) {
114
+
115
+ static createFilePersistenceWithDPAPIError(errorMessage) {
373
116
  return new PersistenceError("DPAPIEncryptedFileError", errorMessage);
374
117
  }
375
118
  /**
376
119
  * Error thrown when using the cross platform lock.
377
120
  */
378
- ;
379
121
 
380
- PersistenceError.createCrossPlatformLockError = function createCrossPlatformLockError(errorMessage) {
122
+
123
+ static createCrossPlatformLockError(errorMessage) {
381
124
  return new PersistenceError("CrossPlatformLockError", errorMessage);
382
- };
125
+ }
126
+ /**
127
+ * Throw cache persistence error
128
+ *
129
+ * @param errorMessage string
130
+ * @returns PersistenceError
131
+ */
132
+
133
+
134
+ static createCachePersistenceError(errorMessage) {
135
+ return new PersistenceError("CachePersistenceError", errorMessage);
136
+ }
137
+ /**
138
+ * Throw unsupported error
139
+ *
140
+ * @param errorMessage string
141
+ * @returns PersistenceError
142
+ */
383
143
 
384
- return PersistenceError;
385
- }( /*#__PURE__*/_wrapNativeSuper(Error));
386
144
 
145
+ static createNotSupportedError(errorMessage) {
146
+ return new PersistenceError("NotSupportedError", errorMessage);
147
+ }
148
+ /**
149
+ * Throw persistence not verified error
150
+ *
151
+ * @param errorMessage string
152
+ * @returns PersistenceError
153
+ */
154
+
155
+
156
+ static createPersistenceNotVerifiedError(errorMessage) {
157
+ return new PersistenceError("PersistenceNotVerifiedError", errorMessage);
158
+ }
159
+ /**
160
+ * Throw persistence creation validation error
161
+ *
162
+ * @param errorMessage string
163
+ * @returns PersistenceError
164
+ */
165
+
166
+
167
+ static createPersistenceNotValidatedError(errorMessage) {
168
+ return new PersistenceError("PersistenceNotValidatedError", errorMessage);
169
+ }
170
+
171
+ }
172
+
173
+ /*
174
+ * Copyright (c) Microsoft Corporation. All rights reserved.
175
+ * Licensed under the MIT License.
176
+ */
387
177
  /**
388
178
  * Cross-process lock that works on all platforms.
389
179
  */
390
180
 
391
- var CrossPlatformLock = /*#__PURE__*/function () {
392
- function CrossPlatformLock(lockFilePath, logger, lockOptions) {
181
+ class CrossPlatformLock {
182
+ constructor(lockFilePath, logger, lockOptions) {
393
183
  this.lockFilePath = lockFilePath;
394
184
  this.retryNumber = lockOptions ? lockOptions.retryNumber : 500;
395
185
  this.retryDelay = lockOptions ? lockOptions.retryDelay : 100;
@@ -402,108 +192,65 @@ var CrossPlatformLock = /*#__PURE__*/function () {
402
192
  */
403
193
 
404
194
 
405
- var _proto = CrossPlatformLock.prototype;
406
-
407
- _proto.lock = function lock() {
408
- try {
409
- var _temp3 = function _temp3(_result3) {
410
- if (_exit2) return _result3;
411
-
412
- _this2.logger.error(pid + " was not able to acquire lock. Exceeded amount of retries set in the options");
413
-
414
- throw PersistenceError.createCrossPlatformLockError("Not able to acquire lock. Exceeded amount of retries set in options");
415
- };
416
-
417
- var _exit2 = false;
418
-
419
- var _this2 = this;
420
-
421
- var _tryCount = 0;
422
-
423
- var _temp4 = _for(function () {
424
- return !_exit2 && _tryCount < _this2.retryNumber;
425
- }, function () {
426
- return _tryCount++;
427
- }, function () {
428
- return _catch(function () {
429
- _this2.logger.info("Pid " + pid + " trying to acquire lock");
430
-
431
- return Promise.resolve(promises.open(_this2.lockFilePath, "wx+")).then(function (_fs$open) {
432
- _this2.lockFileHandle = _fs$open;
433
-
434
- _this2.logger.info("Pid " + pid + " acquired lock");
435
-
436
- return Promise.resolve(_this2.lockFileHandle.write(pid.toString())).then(function () {
437
- _exit2 = true;
438
- });
439
- });
440
- }, function (err) {
441
- return function () {
442
- if (err.code == Constants.EEXIST_ERROR || err.code == Constants.EPERM_ERROR) {
443
- _this2.logger.info(err);
444
-
445
- return Promise.resolve(_this2.sleep(_this2.retryDelay)).then(function () {});
446
- } else {
447
- _this2.logger.error(pid + " was not able to acquire lock. Ran into error: " + err.message);
448
-
449
- throw PersistenceError.createCrossPlatformLockError(err.message);
450
- }
451
- }();
452
- });
453
- });
454
-
455
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
456
- } catch (e) {
457
- return Promise.reject(e);
195
+ async lock() {
196
+ for (let tryCount = 0; tryCount < this.retryNumber; tryCount++) {
197
+ try {
198
+ this.logger.info(`Pid ${pid} trying to acquire lock`);
199
+ this.lockFileHandle = await promises.open(this.lockFilePath, "wx+");
200
+ this.logger.info(`Pid ${pid} acquired lock`);
201
+ await this.lockFileHandle.write(pid.toString());
202
+ return;
203
+ } catch (err) {
204
+ if (err.code === Constants.EEXIST_ERROR || err.code === Constants.EPERM_ERROR) {
205
+ this.logger.info(err);
206
+ await this.sleep(this.retryDelay);
207
+ } else {
208
+ this.logger.error(`${pid} was not able to acquire lock. Ran into error: ${err.message}`);
209
+ throw PersistenceError.createCrossPlatformLockError(err.message);
210
+ }
211
+ }
458
212
  }
213
+
214
+ this.logger.error(`${pid} was not able to acquire lock. Exceeded amount of retries set in the options`);
215
+ throw PersistenceError.createCrossPlatformLockError("Not able to acquire lock. Exceeded amount of retries set in options");
459
216
  }
460
217
  /**
461
218
  * unlocks cache file by deleting .lockfile.
462
219
  */
463
- ;
464
220
 
465
- _proto.unlock = function unlock() {
466
- try {
467
- var _this4 = this;
468
-
469
- return Promise.resolve(_catch(function () {
470
- var _temp5 = function () {
471
- if (_this4.lockFileHandle) {
472
- // if we have a file handle to the .lockfile, delete lock file
473
- return Promise.resolve(promises.unlink(_this4.lockFilePath)).then(function () {
474
- return Promise.resolve(_this4.lockFileHandle.close()).then(function () {
475
- _this4.logger.info("lockfile deleted");
476
- });
477
- });
478
- } else {
479
- _this4.logger.warning("lockfile handle does not exist, so lockfile could not be deleted");
480
- }
481
- }();
482
221
 
483
- if (_temp5 && _temp5.then) return _temp5.then(function () {});
484
- }, function (err) {
485
- if (err.code == Constants.ENOENT_ERROR) {
486
- _this4.logger.warning("Tried to unlock but lockfile does not exist");
487
- } else {
488
- _this4.logger.error(pid + " was not able to release lock. Ran into error: " + err.message);
489
-
490
- throw PersistenceError.createCrossPlatformLockError(err.message);
491
- }
492
- }));
493
- } catch (e) {
494
- return Promise.reject(e);
222
+ async unlock() {
223
+ try {
224
+ if (this.lockFileHandle) {
225
+ // if we have a file handle to the .lockfile, delete lock file
226
+ await promises.unlink(this.lockFilePath);
227
+ await this.lockFileHandle.close();
228
+ this.logger.info("lockfile deleted");
229
+ } else {
230
+ this.logger.warning("lockfile handle does not exist, so lockfile could not be deleted");
231
+ }
232
+ } catch (err) {
233
+ if (err.code === Constants.ENOENT_ERROR) {
234
+ this.logger.info("Tried to unlock but lockfile does not exist");
235
+ } else {
236
+ this.logger.error(`${pid} was not able to release lock. Ran into error: ${err.message}`);
237
+ throw PersistenceError.createCrossPlatformLockError(err.message);
238
+ }
495
239
  }
496
- };
240
+ }
497
241
 
498
- _proto.sleep = function sleep(ms) {
499
- return new Promise(function (resolve) {
242
+ sleep(ms) {
243
+ return new Promise(resolve => {
500
244
  setTimeout(resolve, ms);
501
245
  });
502
- };
246
+ }
503
247
 
504
- return CrossPlatformLock;
505
- }();
248
+ }
506
249
 
250
+ /*
251
+ * Copyright (c) Microsoft Corporation. All rights reserved.
252
+ * Licensed under the MIT License.
253
+ */
507
254
  /**
508
255
  * MSAL cache plugin which enables callers to write the MSAL cache to disk on Windows,
509
256
  * macOs, and Linux.
@@ -518,125 +265,117 @@ var CrossPlatformLock = /*#__PURE__*/function () {
518
265
  * libsecret be installed.
519
266
  */
520
267
 
521
- var PersistenceCachePlugin = /*#__PURE__*/function () {
522
- function PersistenceCachePlugin(persistence, lockOptions) {
268
+ class PersistenceCachePlugin {
269
+ constructor(persistence, lockOptions) {
523
270
  this.persistence = persistence; // initialize logger
524
271
 
525
272
  this.logger = persistence.getLogger(); // create file lock
526
273
 
527
- this.lockFilePath = this.persistence.getFilePath() + ".lockfile";
274
+ this.lockFilePath = `${this.persistence.getFilePath()}.lockfile`;
528
275
  this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions); // initialize default values
529
276
 
530
277
  this.lastSync = 0;
531
278
  this.currentCache = null;
532
279
  }
533
280
  /**
534
- * Reads from storage and avoids saves an in memory copy. If persistence has not been updated
281
+ * Reads from storage and saves an in-memory copy. If persistence has not been updated
535
282
  * since last time data was read, in memory copy is used.
283
+ *
284
+ * If cacheContext.cacheHasChanged === true, then file lock is created and not deleted until
285
+ * afterCacheAccess() is called, to prevent the cache file from changing in between
286
+ * beforeCacheAccess() and afterCacheAccess().
536
287
  */
537
288
 
538
289
 
539
- var _proto = PersistenceCachePlugin.prototype;
540
-
541
- _proto.readFromStorage = function readFromStorage() {
542
- try {
543
- var _this2 = this;
290
+ async beforeCacheAccess(cacheContext) {
291
+ this.logger.info("Executing before cache access");
292
+ const reloadNecessary = await this.persistence.reloadNecessary(this.lastSync);
544
293
 
545
- _this2.logger.info("Reading from storage");
546
-
547
- return Promise.resolve(_this2.persistence.reloadNecessary(_this2.lastSync)).then(function (_this$persistence$rel) {
548
- function _temp3() {
549
- return _this2.currentCache;
550
- }
294
+ if (!reloadNecessary && this.currentCache !== null) {
295
+ if (cacheContext.cacheHasChanged) {
296
+ this.logger.verbose("Cache context has changed");
297
+ await this.crossPlatformLock.lock();
298
+ }
551
299
 
552
- var _temp2 = function () {
553
- if (_this$persistence$rel || _this2.currentCache == null) {
554
- var _temp4 = _finallyRethrows(function () {
555
- _this2.logger.info("Reload necessary. Last sync time: " + _this2.lastSync);
556
-
557
- return Promise.resolve(_this2.crossPlatformLock.lock()).then(function () {
558
- return Promise.resolve(_this2.persistence.load()).then(function (_this$persistence$loa) {
559
- _this2.currentCache = _this$persistence$loa;
560
- _this2.lastSync = new Date().getTime();
561
-
562
- _this2.logger.info("Last sync time updated to: " + _this2.lastSync);
563
- });
564
- });
565
- }, function (_wasThrown, _result) {
566
- return Promise.resolve(_this2.crossPlatformLock.unlock()).then(function () {
567
- _this2.logger.info("Pid " + pid + " Released lock");
568
-
569
- if (_wasThrown) throw _result;
570
- return _result;
571
- });
572
- });
573
-
574
- if (_temp4 && _temp4.then) return _temp4.then(function () {});
575
- }
576
- }();
300
+ return;
301
+ }
577
302
 
578
- return _temp2 && _temp2.then ? _temp2.then(_temp3) : _temp3(_temp2);
579
- });
580
- } catch (e) {
581
- return Promise.reject(e);
303
+ try {
304
+ this.logger.info(`Reload necessary. Last sync time: ${this.lastSync}`);
305
+ await this.crossPlatformLock.lock();
306
+ this.currentCache = await this.persistence.load();
307
+ this.lastSync = new Date().getTime();
308
+ cacheContext.tokenCache.deserialize(this.currentCache);
309
+ this.logger.info(`Last sync time updated to: ${this.lastSync}`);
310
+ } finally {
311
+ if (!cacheContext.cacheHasChanged) {
312
+ await this.crossPlatformLock.unlock();
313
+ this.logger.info(`Pid ${pid} released lock`);
314
+ } else {
315
+ this.logger.info(`Pid ${pid} beforeCacheAccess did not release lock`);
316
+ }
582
317
  }
583
318
  }
584
319
  /**
585
- * Writes to storage. If persistence has not been updated since last time data was read,
586
- * reads and latest state from persistence, sends state via callback, and updates in memory copy.
320
+ * Writes to storage if MSAL in memory copy of cache has been changed.
587
321
  */
588
- ;
589
322
 
590
- _proto.writeToStorage = function writeToStorage(callback) {
323
+
324
+ async afterCacheAccess(cacheContext) {
325
+ this.logger.info("Executing after cache access");
326
+
591
327
  try {
592
- var _this4 = this;
593
-
594
- var _temp8 = _finallyRethrows(function () {
595
- _this4.logger.info("Writing to storage");
596
-
597
- return Promise.resolve(_this4.crossPlatformLock.lock()).then(function () {
598
- return Promise.resolve(_this4.persistence.reloadNecessary(_this4.lastSync)).then(function (_this3$persistence$re) {
599
- function _temp6() {
600
- return Promise.resolve(callback(_this4.currentCache)).then(function (_callback) {
601
- _this4.currentCache = _callback;
602
- return Promise.resolve(_this4.persistence.save(_this4.currentCache)).then(function () {});
603
- });
604
- }
605
-
606
- var _temp5 = function () {
607
- if (_this3$persistence$re) {
608
- _this4.logger.info("Reload necessary. Last sync time: " + _this4.lastSync);
609
-
610
- return Promise.resolve(_this4.persistence.load()).then(function (_this3$persistence$lo) {
611
- _this4.currentCache = _this3$persistence$lo;
612
- _this4.lastSync = new Date().getTime();
613
-
614
- _this4.logger.info("Last sync time updated to: " + _this4.lastSync);
615
- });
616
- }
617
- }();
618
-
619
- return _temp5 && _temp5.then ? _temp5.then(_temp6) : _temp6(_temp5);
620
- });
621
- });
622
- }, function (_wasThrown2, _result2) {
623
- return Promise.resolve(_this4.crossPlatformLock.unlock()).then(function () {
624
- _this4.logger.info("Pid " + pid + " Released lock");
625
-
626
- if (_wasThrown2) throw _result2;
627
- return _result2;
628
- });
629
- });
328
+ if (cacheContext.cacheHasChanged) {
329
+ this.logger.info("Msal in-memory cache has changed. Writing changes to persistence");
330
+ this.currentCache = cacheContext.tokenCache.serialize();
331
+ await this.persistence.save(this.currentCache);
332
+ } else {
333
+ this.logger.info("Msal in-memory cache has not changed. Did not write to persistence");
334
+ }
335
+ } finally {
336
+ await this.crossPlatformLock.unlock();
337
+ this.logger.info(`Pid ${pid} afterCacheAccess released lock`);
338
+ }
339
+ }
340
+
341
+ }
630
342
 
631
- return Promise.resolve(_temp8 && _temp8.then ? _temp8.then(function () {}) : void 0);
343
+ /*
344
+ * Copyright (c) Microsoft Corporation. All rights reserved.
345
+ * Licensed under the MIT License.
346
+ */
347
+ class BasePersistence {
348
+ async verifyPersistence() {
349
+ // We are using a different location for the test to avoid overriding the functional cache
350
+ const persistenceValidator = await this.createForPersistenceValidation();
351
+
352
+ try {
353
+ await persistenceValidator.save(Constants.PERSISTENCE_TEST_DATA);
354
+ const retrievedDummyData = await persistenceValidator.load();
355
+
356
+ if (!retrievedDummyData) {
357
+ throw PersistenceError.createCachePersistenceError("Persistence check failed. Data was written but it could not be read. " + "Possible cause: on Linux, LibSecret is installed but D-Bus isn't running \
358
+ because it cannot be started over SSH.");
359
+ }
360
+
361
+ if (retrievedDummyData !== Constants.PERSISTENCE_TEST_DATA) {
362
+ throw PersistenceError.createCachePersistenceError(`Persistence check failed. Data written ${Constants.PERSISTENCE_TEST_DATA} is different \
363
+ from data read ${retrievedDummyData}`);
364
+ }
365
+
366
+ await persistenceValidator.delete();
367
+ return true;
632
368
  } catch (e) {
633
- return Promise.reject(e);
369
+ throw PersistenceError.createCachePersistenceError(`Verifing persistence failed with the error: ${e}`);
634
370
  }
635
- };
371
+ }
636
372
 
637
- return PersistenceCachePlugin;
638
- }();
373
+ }
639
374
 
375
+ /*
376
+ * Copyright (c) Microsoft Corporation. All rights reserved.
377
+ * Licensed under the MIT License.
378
+ */
640
379
  /**
641
380
  * Reads and writes data to file specified by file location. File contents are not
642
381
  * encrypted.
@@ -645,203 +384,162 @@ var PersistenceCachePlugin = /*#__PURE__*/function () {
645
384
  * file and any directories in the path recursively.
646
385
  */
647
386
 
648
- var FilePersistence = /*#__PURE__*/function () {
649
- function FilePersistence() {}
650
-
651
- FilePersistence.create = function create(fileLocation, loggerOptions) {
652
- try {
653
- var filePersistence = new FilePersistence();
654
- filePersistence.filePath = fileLocation;
655
- filePersistence.logger = new Logger(loggerOptions || FilePersistence.createDefaultLoggerOptions());
656
- return Promise.resolve(filePersistence.createCacheFile()).then(function () {
657
- return filePersistence;
658
- });
659
- } catch (e) {
660
- return Promise.reject(e);
661
- }
662
- };
663
-
664
- var _proto = FilePersistence.prototype;
387
+ class FilePersistence extends BasePersistence {
388
+ static async create(fileLocation, loggerOptions) {
389
+ const filePersistence = new FilePersistence();
390
+ filePersistence.filePath = fileLocation;
391
+ filePersistence.logger = new Logger(loggerOptions || FilePersistence.createDefaultLoggerOptions());
392
+ await filePersistence.createCacheFile();
393
+ return filePersistence;
394
+ }
665
395
 
666
- _proto.save = function save(contents) {
396
+ async save(contents) {
667
397
  try {
668
- var _this2 = this;
669
-
670
- return Promise.resolve(_catch(function () {
671
- return Promise.resolve(promises.writeFile(_this2.getFilePath(), contents, "utf-8")).then(function () {});
672
- }, function (err) {
673
- throw PersistenceError.createFileSystemError(err.code, err.message);
674
- }));
675
- } catch (e) {
676
- return Promise.reject(e);
398
+ await promises.writeFile(this.getFilePath(), contents, "utf-8");
399
+ } catch (err) {
400
+ throw PersistenceError.createFileSystemError(err.code, err.message);
677
401
  }
678
- };
402
+ }
679
403
 
680
- _proto.saveBuffer = function saveBuffer(contents) {
404
+ async saveBuffer(contents) {
681
405
  try {
682
- var _this4 = this;
683
-
684
- return Promise.resolve(_catch(function () {
685
- return Promise.resolve(promises.writeFile(_this4.getFilePath(), contents)).then(function () {});
686
- }, function (err) {
687
- throw PersistenceError.createFileSystemError(err.code, err.message);
688
- }));
689
- } catch (e) {
690
- return Promise.reject(e);
406
+ await promises.writeFile(this.getFilePath(), contents);
407
+ } catch (err) {
408
+ throw PersistenceError.createFileSystemError(err.code, err.message);
691
409
  }
692
- };
410
+ }
693
411
 
694
- _proto.load = function load() {
412
+ async load() {
695
413
  try {
696
- var _this6 = this;
697
-
698
- return Promise.resolve(_catch(function () {
699
- return Promise.resolve(promises.readFile(_this6.getFilePath(), "utf-8"));
700
- }, function (err) {
701
- throw PersistenceError.createFileSystemError(err.code, err.message);
702
- }));
703
- } catch (e) {
704
- return Promise.reject(e);
414
+ return await promises.readFile(this.getFilePath(), "utf-8");
415
+ } catch (err) {
416
+ throw PersistenceError.createFileSystemError(err.code, err.message);
705
417
  }
706
- };
418
+ }
707
419
 
708
- _proto.loadBuffer = function loadBuffer() {
420
+ async loadBuffer() {
709
421
  try {
710
- var _this8 = this;
711
-
712
- return Promise.resolve(_catch(function () {
713
- return Promise.resolve(promises.readFile(_this8.getFilePath()));
714
- }, function (err) {
715
- throw PersistenceError.createFileSystemError(err.code, err.message);
716
- }));
717
- } catch (e) {
718
- return Promise.reject(e);
422
+ return await promises.readFile(this.getFilePath());
423
+ } catch (err) {
424
+ throw PersistenceError.createFileSystemError(err.code, err.message);
719
425
  }
720
- };
426
+ }
721
427
 
722
- _proto["delete"] = function _delete() {
428
+ async delete() {
723
429
  try {
724
- var _this10 = this;
725
-
726
- return Promise.resolve(_catch(function () {
727
- return Promise.resolve(promises.unlink(_this10.getFilePath())).then(function () {
728
- return true;
729
- });
730
- }, function (err) {
731
- if (err.code == Constants.ENOENT_ERROR) {
732
- // file does not exist, so it was not deleted
733
- _this10.logger.warning("Cache file does not exist, so it could not be deleted");
734
-
735
- return false;
736
- }
430
+ await promises.unlink(this.getFilePath());
431
+ return true;
432
+ } catch (err) {
433
+ if (err.code === Constants.ENOENT_ERROR) {
434
+ // file does not exist, so it was not deleted
435
+ this.logger.warning("Cache file does not exist, so it could not be deleted");
436
+ return false;
437
+ }
737
438
 
738
- throw PersistenceError.createFileSystemError(err.code, err.message);
739
- }));
740
- } catch (e) {
741
- return Promise.reject(e);
439
+ throw PersistenceError.createFileSystemError(err.code, err.message);
742
440
  }
743
- };
441
+ }
744
442
 
745
- _proto.getFilePath = function getFilePath() {
443
+ getFilePath() {
746
444
  return this.filePath;
747
- };
748
-
749
- _proto.reloadNecessary = function reloadNecessary(lastSync) {
750
- try {
751
- var _this12 = this;
445
+ }
752
446
 
753
- return Promise.resolve(_this12.timeLastModified()).then(function (_this11$timeLastModif) {
754
- return lastSync < _this11$timeLastModif;
755
- });
756
- } catch (e) {
757
- return Promise.reject(e);
758
- }
759
- };
447
+ async reloadNecessary(lastSync) {
448
+ return lastSync < (await this.timeLastModified());
449
+ }
760
450
 
761
- _proto.getLogger = function getLogger() {
451
+ getLogger() {
762
452
  return this.logger;
763
- };
453
+ }
764
454
 
765
- FilePersistence.createDefaultLoggerOptions = function createDefaultLoggerOptions() {
455
+ createForPersistenceValidation() {
456
+ const testCacheFileLocation = `${dirname(this.filePath)}/test.cache`;
457
+ return FilePersistence.create(testCacheFileLocation);
458
+ }
459
+
460
+ static createDefaultLoggerOptions() {
766
461
  return {
767
- loggerCallback: function loggerCallback() {// allow users to not set loggerCallback
462
+ loggerCallback: () => {// allow users to not set loggerCallback
768
463
  },
769
464
  piiLoggingEnabled: false,
770
465
  logLevel: LogLevel.Info
771
466
  };
772
- };
467
+ }
773
468
 
774
- _proto.timeLastModified = function timeLastModified() {
469
+ async timeLastModified() {
775
470
  try {
776
- var _this14 = this;
777
-
778
- return Promise.resolve(_catch(function () {
779
- return Promise.resolve(promises.stat(_this14.filePath)).then(function (stats) {
780
- return stats.mtime.getTime();
781
- });
782
- }, function (err) {
783
- if (err.code == Constants.ENOENT_ERROR) {
784
- // file does not exist, so it's never been modified
785
- _this14.logger.verbose("Cache file does not exist");
786
-
787
- return 0;
788
- }
471
+ const stats = await promises.stat(this.filePath);
472
+ return stats.mtime.getTime();
473
+ } catch (err) {
474
+ if (err.code === Constants.ENOENT_ERROR) {
475
+ // file does not exist, so it's never been modified
476
+ this.logger.verbose("Cache file does not exist");
477
+ return 0;
478
+ }
789
479
 
790
- throw PersistenceError.createFileSystemError(err.code, err.message);
791
- }));
792
- } catch (e) {
793
- return Promise.reject(e);
480
+ throw PersistenceError.createFileSystemError(err.code, err.message);
794
481
  }
795
- };
482
+ }
483
+
484
+ async createCacheFile() {
485
+ await this.createFileDirectory(); // File is created only if it does not exist
796
486
 
797
- _proto.createCacheFile = function createCacheFile() {
487
+ const fileHandle = await promises.open(this.filePath, "a");
488
+ await fileHandle.close();
489
+ this.logger.info(`File created at ${this.filePath}`);
490
+ }
491
+
492
+ async createFileDirectory() {
798
493
  try {
799
- var _this16 = this;
800
-
801
- return Promise.resolve(_this16.createFileDirectory()).then(function () {
802
- // File is created only if it does not exist
803
- return Promise.resolve(promises.open(_this16.filePath, "a")).then(function (fileHandle) {
804
- return Promise.resolve(fileHandle.close()).then(function () {
805
- _this16.logger.info("File created at " + _this16.filePath);
806
- });
807
- });
494
+ await promises.mkdir(dirname(this.filePath), {
495
+ recursive: true
808
496
  });
809
- } catch (e) {
810
- return Promise.reject(e);
497
+ } catch (err) {
498
+ if (err.code === Constants.EEXIST_ERROR) {
499
+ this.logger.info(`Directory ${dirname(this.filePath)} already exists`);
500
+ } else {
501
+ throw PersistenceError.createFileSystemError(err.code, err.message);
502
+ }
811
503
  }
812
- };
504
+ }
813
505
 
814
- _proto.createFileDirectory = function createFileDirectory() {
815
- try {
816
- var _this18 = this;
817
-
818
- return Promise.resolve(_catch(function () {
819
- return Promise.resolve(promises.mkdir(dirname(_this18.filePath), {
820
- recursive: true
821
- })).then(function () {});
822
- }, function (err) {
823
- if (err.code == Constants.EEXIST_ERROR) {
824
- _this18.logger.info("Directory " + dirname(_this18.filePath) + " already exists");
825
- } else {
826
- throw PersistenceError.createFileSystemError(err.code, err.message);
827
- }
828
- }));
829
- } catch (e) {
830
- return Promise.reject(e);
831
- }
832
- };
506
+ }
507
+
508
+ /*
509
+ * Copyright (c) Microsoft Corporation. All rights reserved.
510
+ * Licensed under the MIT License.
511
+ */
833
512
 
834
- return FilePersistence;
835
- }();
513
+ /* eslint-disable-next-line @typescript-eslint/no-var-requires, no-var, import/no-commonjs */
514
+ var Dpapi = /*#__PURE__*/require("../build/Release/dpapi.node");
836
515
 
837
516
  /*
838
517
  * Copyright (c) Microsoft Corporation. All rights reserved.
839
518
  * Licensed under the MIT License.
840
519
  */
841
520
 
842
- /* eslint-disable-next-line @typescript-eslint/no-var-requires, no-var */
843
- var Dpapi = /*#__PURE__*/require("bindings")("dpapi");
521
+ /**
522
+ * Specifies the scope of the data protection - either the current user or the local
523
+ * machine.
524
+ *
525
+ * You do not need a key to protect or unprotect the data.
526
+ * If you set the Scope to CurrentUser, only applications running on your credentials can
527
+ * unprotect the data; however, that means that any application running on your credentials
528
+ * can access the protected data. If you set the Scope to LocalMachine, any full-trust
529
+ * application on the computer can unprotect, access, and modify the data.
530
+ *
531
+ */
532
+ var DataProtectionScope;
844
533
 
534
+ (function (DataProtectionScope) {
535
+ DataProtectionScope["CurrentUser"] = "CurrentUser";
536
+ DataProtectionScope["LocalMachine"] = "LocalMachine";
537
+ })(DataProtectionScope || (DataProtectionScope = {}));
538
+
539
+ /*
540
+ * Copyright (c) Microsoft Corporation. All rights reserved.
541
+ * Licensed under the MIT License.
542
+ */
845
543
  /**
846
544
  * Uses CryptProtectData and CryptUnprotectData on Windows to encrypt and decrypt file contents.
847
545
  *
@@ -849,117 +547,70 @@ var Dpapi = /*#__PURE__*/require("bindings")("dpapi");
849
547
  * optionalEntropy: Password or other additional entropy used to encrypt the data
850
548
  */
851
549
 
852
- var FilePersistenceWithDataProtection = /*#__PURE__*/function () {
853
- function FilePersistenceWithDataProtection(scope, optionalEntropy) {
550
+ class FilePersistenceWithDataProtection extends BasePersistence {
551
+ constructor(scope, optionalEntropy) {
552
+ super();
854
553
  this.scope = scope;
855
554
  this.optionalEntropy = optionalEntropy ? Buffer.from(optionalEntropy, "utf-8") : null;
856
555
  }
857
556
 
858
- FilePersistenceWithDataProtection.create = function create(fileLocation, scope, optionalEntropy, loggerOptions) {
859
- try {
860
- var persistence = new FilePersistenceWithDataProtection(scope, optionalEntropy);
861
- return Promise.resolve(FilePersistence.create(fileLocation, loggerOptions)).then(function (_FilePersistence$crea) {
862
- persistence.filePersistence = _FilePersistence$crea;
863
- return persistence;
864
- });
865
- } catch (e) {
866
- return Promise.reject(e);
867
- }
868
- };
869
-
870
- var _proto = FilePersistenceWithDataProtection.prototype;
557
+ static async create(fileLocation, scope, optionalEntropy, loggerOptions) {
558
+ const persistence = new FilePersistenceWithDataProtection(scope, optionalEntropy);
559
+ persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
560
+ return persistence;
561
+ }
871
562
 
872
- _proto.save = function save(contents) {
563
+ async save(contents) {
873
564
  try {
874
- var _this2 = this;
875
-
876
- return Promise.resolve(_catch(function () {
877
- var encryptedContents = Dpapi.protectData(Buffer.from(contents, "utf-8"), _this2.optionalEntropy, _this2.scope.toString());
878
- return Promise.resolve(_this2.filePersistence.saveBuffer(encryptedContents)).then(function () {});
879
- }, function (err) {
880
- throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
881
- }));
882
- } catch (e) {
883
- return Promise.reject(e);
565
+ const encryptedContents = Dpapi.protectData(Buffer.from(contents, "utf-8"), this.optionalEntropy, this.scope.toString());
566
+ await this.filePersistence.saveBuffer(encryptedContents);
567
+ } catch (err) {
568
+ throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
884
569
  }
885
- };
570
+ }
886
571
 
887
- _proto.load = function load() {
572
+ async load() {
888
573
  try {
889
- var _this4 = this;
890
-
891
- return Promise.resolve(_catch(function () {
892
- return Promise.resolve(_this4.filePersistence.loadBuffer()).then(function (encryptedContents) {
893
- if (typeof encryptedContents === "undefined" || !encryptedContents || 0 === encryptedContents.length) {
894
- _this4.filePersistence.getLogger().info("Encrypted contents loaded from file were null or empty");
895
-
896
- return null;
897
- }
898
-
899
- return Dpapi.unprotectData(encryptedContents, _this4.optionalEntropy, _this4.scope.toString()).toString();
900
- });
901
- }, function (err) {
902
- throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
903
- }));
904
- } catch (e) {
905
- return Promise.reject(e);
906
- }
907
- };
574
+ const encryptedContents = await this.filePersistence.loadBuffer();
908
575
 
909
- _proto["delete"] = function _delete() {
910
- try {
911
- var _this6 = this;
576
+ if (typeof encryptedContents === "undefined" || !encryptedContents || 0 === encryptedContents.length) {
577
+ this.filePersistence.getLogger().info("Encrypted contents loaded from file were null or empty");
578
+ return null;
579
+ }
912
580
 
913
- return Promise.resolve(_this6.filePersistence["delete"]());
914
- } catch (e) {
915
- return Promise.reject(e);
581
+ return Dpapi.unprotectData(encryptedContents, this.optionalEntropy, this.scope.toString()).toString();
582
+ } catch (err) {
583
+ throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
916
584
  }
917
- };
585
+ }
918
586
 
919
- _proto.reloadNecessary = function reloadNecessary(lastSync) {
920
- try {
921
- var _this8 = this;
587
+ async delete() {
588
+ return this.filePersistence.delete();
589
+ }
922
590
 
923
- return Promise.resolve(_this8.filePersistence.reloadNecessary(lastSync));
924
- } catch (e) {
925
- return Promise.reject(e);
926
- }
927
- };
591
+ async reloadNecessary(lastSync) {
592
+ return this.filePersistence.reloadNecessary(lastSync);
593
+ }
928
594
 
929
- _proto.getFilePath = function getFilePath() {
595
+ getFilePath() {
930
596
  return this.filePersistence.getFilePath();
931
- };
597
+ }
932
598
 
933
- _proto.getLogger = function getLogger() {
599
+ getLogger() {
934
600
  return this.filePersistence.getLogger();
935
- };
601
+ }
602
+
603
+ createForPersistenceValidation() {
604
+ const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
605
+ return FilePersistenceWithDataProtection.create(testCacheFileLocation, DataProtectionScope.CurrentUser);
606
+ }
936
607
 
937
- return FilePersistenceWithDataProtection;
938
- }();
608
+ }
939
609
 
940
610
  /*
941
611
  * Copyright (c) Microsoft Corporation. All rights reserved.
942
612
  * Licensed under the MIT License.
943
613
  */
944
-
945
- /**
946
- * Specifies the scope of the data protection - either the current user or the local
947
- * machine.
948
- *
949
- * You do not need a key to protect or unprotect the data.
950
- * If you set the Scope to CurrentUser, only applications running on your credentials can
951
- * unprotect the data; however, that means that any application running on your credentials
952
- * can access the protected data. If you set the Scope to LocalMachine, any full-trust
953
- * application on the computer can unprotect, access, and modify the data.
954
- *
955
- */
956
- var DataProtectionScope;
957
-
958
- (function (DataProtectionScope) {
959
- DataProtectionScope["CurrentUser"] = "CurrentUser";
960
- DataProtectionScope["LocalMachine"] = "LocalMachine";
961
- })(DataProtectionScope || (DataProtectionScope = {}));
962
-
963
614
  /**
964
615
  * Uses reads and writes passwords to macOS keychain
965
616
  *
@@ -967,99 +618,70 @@ var DataProtectionScope;
967
618
  * accountName: Account under which password should be stored
968
619
  */
969
620
 
970
- var KeychainPersistence = /*#__PURE__*/function () {
971
- function KeychainPersistence(serviceName, accountName) {
621
+ class KeychainPersistence extends BasePersistence {
622
+ constructor(serviceName, accountName) {
623
+ super();
972
624
  this.serviceName = serviceName;
973
625
  this.accountName = accountName;
974
626
  }
975
627
 
976
- KeychainPersistence.create = function create(fileLocation, serviceName, accountName, loggerOptions) {
977
- try {
978
- var persistence = new KeychainPersistence(serviceName, accountName);
979
- return Promise.resolve(FilePersistence.create(fileLocation, loggerOptions)).then(function (_FilePersistence$crea) {
980
- persistence.filePersistence = _FilePersistence$crea;
981
- return persistence;
982
- });
983
- } catch (e) {
984
- return Promise.reject(e);
985
- }
986
- };
987
-
988
- var _proto = KeychainPersistence.prototype;
628
+ static async create(fileLocation, serviceName, accountName, loggerOptions) {
629
+ const persistence = new KeychainPersistence(serviceName, accountName);
630
+ persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
631
+ return persistence;
632
+ }
989
633
 
990
- _proto.save = function save(contents) {
634
+ async save(contents) {
991
635
  try {
992
- var _temp3 = function _temp3(_result) {
993
- return _exit2 ? _result : Promise.resolve(_this2.filePersistence.save("{}")).then(function () {});
994
- };
995
-
996
- var _exit2 = false;
636
+ await setPassword(this.serviceName, this.accountName, contents);
637
+ } catch (err) {
638
+ throw PersistenceError.createKeychainPersistenceError(err.message);
639
+ } // Write dummy data to update file mtime
997
640
 
998
- var _this2 = this;
999
641
 
1000
- var _temp4 = _catch(function () {
1001
- return Promise.resolve(setPassword(_this2.serviceName, _this2.accountName, contents)).then(function () {});
1002
- }, function (err) {
1003
- throw PersistenceError.createKeychainPersistenceError(err.message);
1004
- });
1005
-
1006
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4)); // Write dummy data to update file mtime
1007
- } catch (e) {
1008
- return Promise.reject(e);
1009
- }
1010
- };
642
+ await this.filePersistence.save("{}");
643
+ }
1011
644
 
1012
- _proto.load = function load() {
645
+ async load() {
1013
646
  try {
1014
- var _this4 = this;
1015
-
1016
- return Promise.resolve(_catch(function () {
1017
- return Promise.resolve(getPassword(_this4.serviceName, _this4.accountName));
1018
- }, function (err) {
1019
- throw PersistenceError.createKeychainPersistenceError(err.message);
1020
- }));
1021
- } catch (e) {
1022
- return Promise.reject(e);
647
+ return await getPassword(this.serviceName, this.accountName);
648
+ } catch (err) {
649
+ throw PersistenceError.createKeychainPersistenceError(err.message);
1023
650
  }
1024
- };
651
+ }
1025
652
 
1026
- _proto["delete"] = function _delete() {
653
+ async delete() {
1027
654
  try {
1028
- var _this6 = this;
1029
-
1030
- return Promise.resolve(_catch(function () {
1031
- return Promise.resolve(_this6.filePersistence["delete"]()).then(function () {
1032
- return Promise.resolve(deletePassword(_this6.serviceName, _this6.accountName));
1033
- });
1034
- }, function (err) {
1035
- throw PersistenceError.createKeychainPersistenceError(err.message);
1036
- }));
1037
- } catch (e) {
1038
- return Promise.reject(e);
655
+ await this.filePersistence.delete();
656
+ return await deletePassword(this.serviceName, this.accountName);
657
+ } catch (err) {
658
+ throw PersistenceError.createKeychainPersistenceError(err.message);
1039
659
  }
1040
- };
1041
-
1042
- _proto.reloadNecessary = function reloadNecessary(lastSync) {
1043
- try {
1044
- var _this8 = this;
660
+ }
1045
661
 
1046
- return Promise.resolve(_this8.filePersistence.reloadNecessary(lastSync));
1047
- } catch (e) {
1048
- return Promise.reject(e);
1049
- }
1050
- };
662
+ async reloadNecessary(lastSync) {
663
+ return this.filePersistence.reloadNecessary(lastSync);
664
+ }
1051
665
 
1052
- _proto.getFilePath = function getFilePath() {
666
+ getFilePath() {
1053
667
  return this.filePersistence.getFilePath();
1054
- };
668
+ }
1055
669
 
1056
- _proto.getLogger = function getLogger() {
670
+ getLogger() {
1057
671
  return this.filePersistence.getLogger();
1058
- };
672
+ }
1059
673
 
1060
- return KeychainPersistence;
1061
- }();
674
+ createForPersistenceValidation() {
675
+ const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
676
+ return KeychainPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
677
+ }
678
+
679
+ }
1062
680
 
681
+ /*
682
+ * Copyright (c) Microsoft Corporation. All rights reserved.
683
+ * Licensed under the MIT License.
684
+ */
1063
685
  /**
1064
686
  * Uses reads and writes passwords to Secret Service API/libsecret. Requires libsecret
1065
687
  * to be installed.
@@ -1068,98 +690,215 @@ var KeychainPersistence = /*#__PURE__*/function () {
1068
690
  * accountName: Account under which password should be stored
1069
691
  */
1070
692
 
1071
- var LibSecretPersistence = /*#__PURE__*/function () {
1072
- function LibSecretPersistence(serviceName, accountName) {
693
+ class LibSecretPersistence extends BasePersistence {
694
+ constructor(serviceName, accountName) {
695
+ super();
1073
696
  this.serviceName = serviceName;
1074
697
  this.accountName = accountName;
1075
698
  }
1076
699
 
1077
- LibSecretPersistence.create = function create(fileLocation, serviceName, accountName, loggerOptions) {
700
+ static async create(fileLocation, serviceName, accountName, loggerOptions) {
701
+ const persistence = new LibSecretPersistence(serviceName, accountName);
702
+ persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
703
+ return persistence;
704
+ }
705
+
706
+ async save(contents) {
1078
707
  try {
1079
- var persistence = new LibSecretPersistence(serviceName, accountName);
1080
- return Promise.resolve(FilePersistence.create(fileLocation, loggerOptions)).then(function (_FilePersistence$crea) {
1081
- persistence.filePersistence = _FilePersistence$crea;
1082
- return persistence;
1083
- });
1084
- } catch (e) {
1085
- return Promise.reject(e);
1086
- }
1087
- };
708
+ await setPassword(this.serviceName, this.accountName, contents);
709
+ } catch (err) {
710
+ throw PersistenceError.createLibSecretError(err.message);
711
+ } // Write dummy data to update file mtime
1088
712
 
1089
- var _proto = LibSecretPersistence.prototype;
1090
713
 
1091
- _proto.save = function save(contents) {
714
+ await this.filePersistence.save("{}");
715
+ }
716
+
717
+ async load() {
1092
718
  try {
1093
- var _temp3 = function _temp3(_result) {
1094
- return _exit2 ? _result : Promise.resolve(_this2.filePersistence.save("{}")).then(function () {});
1095
- };
719
+ return await getPassword(this.serviceName, this.accountName);
720
+ } catch (err) {
721
+ throw PersistenceError.createLibSecretError(err.message);
722
+ }
723
+ }
1096
724
 
1097
- var _exit2 = false;
725
+ async delete() {
726
+ try {
727
+ await this.filePersistence.delete();
728
+ return await deletePassword(this.serviceName, this.accountName);
729
+ } catch (err) {
730
+ throw PersistenceError.createLibSecretError(err.message);
731
+ }
732
+ }
1098
733
 
1099
- var _this2 = this;
734
+ async reloadNecessary(lastSync) {
735
+ return this.filePersistence.reloadNecessary(lastSync);
736
+ }
1100
737
 
1101
- var _temp4 = _catch(function () {
1102
- return Promise.resolve(setPassword(_this2.serviceName, _this2.accountName, contents)).then(function () {});
1103
- }, function (err) {
1104
- throw PersistenceError.createLibSecretError(err.message);
1105
- });
738
+ getFilePath() {
739
+ return this.filePersistence.getFilePath();
740
+ }
1106
741
 
1107
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4)); // Write dummy data to update file mtime
1108
- } catch (e) {
1109
- return Promise.reject(e);
1110
- }
1111
- };
742
+ getLogger() {
743
+ return this.filePersistence.getLogger();
744
+ }
1112
745
 
1113
- _proto.load = function load() {
1114
- try {
1115
- var _this4 = this;
746
+ createForPersistenceValidation() {
747
+ const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
748
+ return LibSecretPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
749
+ }
1116
750
 
1117
- return Promise.resolve(_catch(function () {
1118
- return Promise.resolve(getPassword(_this4.serviceName, _this4.accountName));
1119
- }, function (err) {
1120
- throw PersistenceError.createLibSecretError(err.message);
1121
- }));
1122
- } catch (e) {
1123
- return Promise.reject(e);
751
+ }
752
+
753
+ /*
754
+ * Copyright (c) Microsoft Corporation. All rights reserved.
755
+ * Licensed under the MIT License.
756
+ */
757
+ class Environment {
758
+ static get homeEnvVar() {
759
+ return this.getEnvironmentVariable(Constants.ENVIRONMENT.HOME);
760
+ }
761
+
762
+ static get lognameEnvVar() {
763
+ return this.getEnvironmentVariable(Constants.ENVIRONMENT.LOGNAME);
764
+ }
765
+
766
+ static get userEnvVar() {
767
+ return this.getEnvironmentVariable(Constants.ENVIRONMENT.USER);
768
+ }
769
+
770
+ static get lnameEnvVar() {
771
+ return this.getEnvironmentVariable(Constants.ENVIRONMENT.LNAME);
772
+ }
773
+
774
+ static get usernameEnvVar() {
775
+ return this.getEnvironmentVariable(Constants.ENVIRONMENT.USERNAME);
776
+ }
777
+
778
+ static getEnvironmentVariable(name) {
779
+ return process.env[name];
780
+ }
781
+
782
+ static getEnvironmentPlatform() {
783
+ return process.platform;
784
+ }
785
+
786
+ static isWindowsPlatform() {
787
+ return this.getEnvironmentPlatform() === Platform.WINDOWS;
788
+ }
789
+
790
+ static isLinuxPlatform() {
791
+ return this.getEnvironmentPlatform() === Platform.LINUX;
792
+ }
793
+
794
+ static isMacPlatform() {
795
+ return this.getEnvironmentPlatform() === Platform.MACOS;
796
+ }
797
+
798
+ static isLinuxRootUser() {
799
+ return process.getuid() === Constants.LINUX_ROOT_USER_GUID;
800
+ }
801
+
802
+ static getUserRootDirectory() {
803
+ return !this.isWindowsPlatform ? this.getUserHomeDirOnUnix() : this.getUserHomeDirOnWindows();
804
+ }
805
+
806
+ static getUserHomeDirOnWindows() {
807
+ return this.getEnvironmentVariable(Constants.ENVIRONMENT.LOCAL_APPLICATION_DATA);
808
+ }
809
+
810
+ static getUserHomeDirOnUnix() {
811
+ if (this.isWindowsPlatform()) {
812
+ throw PersistenceError.createNotSupportedError("Getting the user home directory for unix is not supported in windows");
1124
813
  }
1125
- };
1126
814
 
1127
- _proto["delete"] = function _delete() {
1128
- try {
1129
- var _this6 = this;
1130
-
1131
- return Promise.resolve(_catch(function () {
1132
- return Promise.resolve(_this6.filePersistence["delete"]()).then(function () {
1133
- return Promise.resolve(deletePassword(_this6.serviceName, _this6.accountName));
1134
- });
1135
- }, function (err) {
1136
- throw PersistenceError.createLibSecretError(err.message);
1137
- }));
1138
- } catch (e) {
1139
- return Promise.reject(e);
815
+ if (!StringUtils.isEmpty(this.homeEnvVar)) {
816
+ return this.homeEnvVar;
1140
817
  }
1141
- };
1142
818
 
1143
- _proto.reloadNecessary = function reloadNecessary(lastSync) {
1144
- try {
1145
- var _this8 = this;
819
+ let username = null;
1146
820
 
1147
- return Promise.resolve(_this8.filePersistence.reloadNecessary(lastSync));
1148
- } catch (e) {
1149
- return Promise.reject(e);
821
+ if (!StringUtils.isEmpty(this.lognameEnvVar)) {
822
+ username = this.lognameEnvVar;
823
+ } else if (!StringUtils.isEmpty(this.userEnvVar)) {
824
+ username = this.userEnvVar;
825
+ } else if (!StringUtils.isEmpty(this.lnameEnvVar)) {
826
+ username = this.lnameEnvVar;
827
+ } else if (!StringUtils.isEmpty(this.usernameEnvVar)) {
828
+ username = this.usernameEnvVar;
1150
829
  }
1151
- };
1152
830
 
1153
- _proto.getFilePath = function getFilePath() {
1154
- return this.filePersistence.getFilePath();
1155
- };
831
+ if (this.isMacPlatform()) {
832
+ return !StringUtils.isEmpty(username) ? path.join("/Users", username) : null;
833
+ } else if (this.isLinuxPlatform()) {
834
+ if (this.isLinuxRootUser()) {
835
+ return "/root";
836
+ } else {
837
+ return !StringUtils.isEmpty(username) ? path.join("/home", username) : null;
838
+ }
839
+ } else {
840
+ throw PersistenceError.createNotSupportedError("Getting the user home directory for unix is not supported in windows");
841
+ }
842
+ }
1156
843
 
1157
- _proto.getLogger = function getLogger() {
1158
- return this.filePersistence.getLogger();
1159
- };
844
+ }
1160
845
 
1161
- return LibSecretPersistence;
1162
- }();
846
+ /*
847
+ * Copyright (c) Microsoft Corporation. All rights reserved.
848
+ * Licensed under the MIT License.
849
+ */
850
+ class PersistenceCreator {
851
+ static async createPersistence(config) {
852
+ let peristence; // On Windows, uses a DPAPI encrypted file
853
+
854
+ if (Environment.isWindowsPlatform()) {
855
+ if (!config.cachePath || !config.dataProtectionScope) {
856
+ throw PersistenceError.createPersistenceNotValidatedError("Cache path and/or data protection scope not provided for the FilePersistenceWithDataProtection cache plugin");
857
+ }
858
+
859
+ peristence = await FilePersistenceWithDataProtection.create(config.cachePath, DataProtectionScope.CurrentUser, undefined, config.loggerOptions);
860
+ } // On Mac, uses keychain.
861
+ else if (Environment.isMacPlatform()) {
862
+ if (!config.cachePath || !config.serviceName || !config.accountName) {
863
+ throw PersistenceError.createPersistenceNotValidatedError("Cache path, service name and/or account name not provided for the KeychainPersistence cache plugin");
864
+ }
865
+
866
+ peristence = await KeychainPersistence.create(config.cachePath, config.serviceName, config.accountName, config.loggerOptions);
867
+ } // On Linux, uses libsecret to store to secret service. Libsecret has to be installed.
868
+ else if (Environment.isLinuxPlatform()) {
869
+ if (!config.cachePath || !config.serviceName || !config.accountName) {
870
+ throw PersistenceError.createPersistenceNotValidatedError("Cache path, service name and/or account name not provided for the LibSecretPersistence cache plugin");
871
+ }
872
+
873
+ peristence = await LibSecretPersistence.create(config.cachePath, config.serviceName, config.accountName, config.loggerOptions);
874
+ } else {
875
+ throw PersistenceError.createNotSupportedError("The current environment is not supported by msal-node-extensions yet.");
876
+ } // Initially suppress the error thrown during persistence verification to allow us to fallback to plain text
877
+
878
+
879
+ const isPersistenceVerified = await peristence.verifyPersistence().catch(() => false);
880
+
881
+ if (!isPersistenceVerified) {
882
+ if (Environment.isLinuxPlatform() && config.usePlaintextFileOnLinux) {
883
+ if (!config.cachePath) {
884
+ throw PersistenceError.createPersistenceNotValidatedError("Cache path not provided for the FilePersistence cache plugin");
885
+ }
886
+
887
+ peristence = await FilePersistence.create(config.cachePath, config.loggerOptions);
888
+ const isFilePersistenceVerified = await peristence.verifyPersistence();
889
+
890
+ if (isFilePersistenceVerified) {
891
+ return peristence;
892
+ }
893
+ }
894
+
895
+ throw PersistenceError.createPersistenceNotVerifiedError("Persistence could not be verified");
896
+ }
897
+
898
+ return peristence;
899
+ }
900
+
901
+ }
1163
902
 
1164
- export { DataProtectionScope, FilePersistence, FilePersistenceWithDataProtection, KeychainPersistence, LibSecretPersistence, PersistenceCachePlugin };
903
+ export { DataProtectionScope, Environment, FilePersistence, FilePersistenceWithDataProtection, KeychainPersistence, LibSecretPersistence, PersistenceCachePlugin, PersistenceCreator };
1165
904
  //# sourceMappingURL=msal-node-extensions.esm.js.map