@azure/msal-node-extensions 1.0.0-alpha.2 → 1.0.0-alpha.20

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