@azure/msal-node-extensions 1.0.0-alpha.1 → 1.0.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +261 -0
- package/CHANGELOG.md +111 -0
- package/LICENSE +21 -21
- package/README.md +193 -42
- package/binding.gyp +29 -0
- package/dist/error/PersistenceError.d.ts +32 -4
- package/dist/index.d.ts +3 -0
- package/dist/msal-node-extensions.cjs.development.js +615 -849
- package/dist/msal-node-extensions.cjs.development.js.map +1 -1
- package/dist/msal-node-extensions.cjs.production.min.js +1 -1
- package/dist/msal-node-extensions.cjs.production.min.js.map +1 -1
- package/dist/msal-node-extensions.esm.js +625 -864
- package/dist/msal-node-extensions.esm.js.map +1 -1
- package/dist/persistence/BasePersistence.d.ts +5 -0
- package/dist/persistence/FilePersistence.d.ts +4 -2
- package/dist/persistence/FilePersistenceWithDataProtection.d.ts +3 -1
- package/dist/persistence/IPersistence.d.ts +3 -1
- package/dist/persistence/IPersistenceConfiguration.d.ts +8 -0
- package/dist/persistence/KeychainPersistence.d.ts +3 -1
- package/dist/persistence/LibSecretPersistence.d.ts +3 -1
- package/dist/persistence/PersistenceCachePlugin.d.ts +11 -7
- package/dist/persistence/PersistenceCreator.d.ts +5 -0
- package/dist/utils/Constants.d.ts +31 -0
- package/dist/utils/Environment.d.ts +16 -0
- package/package.json +28 -15
- package/src/dpapi-addon/Dpapi.ts +17 -12
- package/src/dpapi-addon/dpapi_addon.h +6 -6
- package/src/dpapi-addon/dpapi_not_supported.cpp +19 -19
- package/src/dpapi-addon/dpapi_win.cpp +114 -114
- package/src/dpapi-addon/main.cpp +32 -32
- package/src/error/PersistenceError.ts +101 -65
- package/src/index.ts +16 -8
- package/src/lock/CrossPlatformLock.ts +89 -82
- package/src/lock/CrossPlatformLockOptions.ts +15 -15
- package/src/persistence/BasePersistence.ts +41 -0
- package/src/persistence/DataProtectionScope.ts +20 -20
- package/src/persistence/FilePersistence.ts +140 -134
- package/src/persistence/FilePersistenceWithDataProtection.ts +92 -84
- package/src/persistence/IPersistence.ts +17 -15
- package/src/persistence/IPersistenceConfiguration.ts +14 -0
- package/src/persistence/KeychainPersistence.ts +86 -78
- package/src/persistence/LibSecretPersistence.ts +87 -79
- package/src/persistence/PersistenceCachePlugin.ts +106 -96
- package/src/persistence/PersistenceCreator.ts +73 -0
- package/src/utils/Constants.ts +62 -24
- package/src/utils/Environment.ts +99 -0
- package/changelog.md +0 -8
|
@@ -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
|
-
|
|
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
|
-
*
|
|
25
|
+
* Operation not permitted. An attempt was made to perform an operation that requires
|
|
26
|
+
* elevated privileges.
|
|
212
27
|
*/
|
|
213
|
-
|
|
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
|
-
|
|
279
|
-
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
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
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
return new PersistenceError("GnomeKeyringError",
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
return new PersistenceError("KeychainError",
|
|
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
|
-
|
|
369
|
-
|
|
370
|
-
return new PersistenceError("DPAPIEncryptedFileError",
|
|
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
|
-
|
|
383
|
-
|
|
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
|
-
|
|
390
|
-
|
|
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
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
-
|
|
221
|
+
|
|
222
|
+
async unlock() {
|
|
459
223
|
try {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
|
|
480
|
-
return new Promise(
|
|
242
|
+
sleep(ms) {
|
|
243
|
+
return new Promise(resolve => {
|
|
481
244
|
setTimeout(resolve, ms);
|
|
482
245
|
});
|
|
483
|
-
}
|
|
246
|
+
}
|
|
484
247
|
|
|
485
|
-
|
|
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
|
-
|
|
503
|
-
|
|
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()
|
|
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
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
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
|
-
|
|
529
|
-
|
|
530
|
-
|
|
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
|
-
|
|
534
|
-
|
|
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
|
-
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
|
|
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
|
|
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
|
-
|
|
323
|
+
|
|
324
|
+
async afterCacheAccess(cacheContext) {
|
|
325
|
+
this.logger.info("Executing after cache access");
|
|
326
|
+
|
|
572
327
|
try {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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
|
-
|
|
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
|
-
|
|
367
|
+
throw PersistenceError.createCachePersistenceError(`Verifing persistence failed with the error: ${e}`);
|
|
615
368
|
}
|
|
616
|
-
}
|
|
369
|
+
}
|
|
617
370
|
|
|
618
|
-
|
|
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
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
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
|
-
|
|
394
|
+
async save(contents) {
|
|
648
395
|
try {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
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
|
-
|
|
402
|
+
async saveBuffer(contents) {
|
|
662
403
|
try {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
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
|
-
|
|
410
|
+
async load() {
|
|
676
411
|
try {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
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
|
-
|
|
418
|
+
async loadBuffer() {
|
|
690
419
|
try {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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
|
-
|
|
426
|
+
async delete() {
|
|
704
427
|
try {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
|
|
720
|
-
}));
|
|
721
|
-
} catch (e) {
|
|
722
|
-
return Promise.reject(e);
|
|
437
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
723
438
|
}
|
|
724
|
-
}
|
|
439
|
+
}
|
|
725
440
|
|
|
726
|
-
|
|
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
|
-
|
|
735
|
-
|
|
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
|
-
|
|
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
|
-
|
|
458
|
+
static createDefaultLoggerOptions() {
|
|
747
459
|
return {
|
|
748
|
-
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
|
-
|
|
467
|
+
async timeLastModified() {
|
|
756
468
|
try {
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
-
|
|
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
|
-
|
|
490
|
+
async createFileDirectory() {
|
|
779
491
|
try {
|
|
780
|
-
|
|
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 (
|
|
791
|
-
|
|
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
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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
|
-
|
|
816
|
-
|
|
511
|
+
/* eslint-disable-next-line @typescript-eslint/no-var-requires, no-var */
|
|
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
|
-
|
|
832
|
-
|
|
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
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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
|
-
|
|
564
|
+
async save(contents) {
|
|
852
565
|
try {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
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
|
-
|
|
573
|
+
async load() {
|
|
867
574
|
try {
|
|
868
|
-
|
|
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
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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
|
|
893
|
-
} catch (
|
|
894
|
-
|
|
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
|
-
|
|
899
|
-
|
|
900
|
-
|
|
588
|
+
async delete() {
|
|
589
|
+
return this.filePersistence.delete();
|
|
590
|
+
}
|
|
901
591
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
}
|
|
906
|
-
};
|
|
592
|
+
async reloadNecessary(lastSync) {
|
|
593
|
+
return this.filePersistence.reloadNecessary(lastSync);
|
|
594
|
+
}
|
|
907
595
|
|
|
908
|
-
|
|
596
|
+
getFilePath() {
|
|
909
597
|
return this.filePersistence.getFilePath();
|
|
910
|
-
}
|
|
598
|
+
}
|
|
911
599
|
|
|
912
|
-
|
|
600
|
+
getLogger() {
|
|
913
601
|
return this.filePersistence.getLogger();
|
|
914
|
-
}
|
|
602
|
+
}
|
|
915
603
|
|
|
916
|
-
|
|
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
|
-
|
|
950
|
-
|
|
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
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
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
|
-
|
|
635
|
+
async save(contents) {
|
|
970
636
|
try {
|
|
971
|
-
|
|
972
|
-
|
|
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
|
-
|
|
986
|
-
|
|
987
|
-
return Promise.reject(e);
|
|
988
|
-
}
|
|
989
|
-
};
|
|
643
|
+
await this.filePersistence.save("{}");
|
|
644
|
+
}
|
|
990
645
|
|
|
991
|
-
|
|
646
|
+
async load() {
|
|
992
647
|
try {
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
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
|
-
|
|
654
|
+
async delete() {
|
|
1006
655
|
try {
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
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
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
}
|
|
1029
|
-
};
|
|
663
|
+
async reloadNecessary(lastSync) {
|
|
664
|
+
return this.filePersistence.reloadNecessary(lastSync);
|
|
665
|
+
}
|
|
1030
666
|
|
|
1031
|
-
|
|
667
|
+
getFilePath() {
|
|
1032
668
|
return this.filePersistence.getFilePath();
|
|
1033
|
-
}
|
|
669
|
+
}
|
|
1034
670
|
|
|
1035
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1051
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
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
|
-
|
|
715
|
+
await this.filePersistence.save("{}");
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
async load() {
|
|
1071
719
|
try {
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
720
|
+
return await getPassword(this.serviceName, this.accountName);
|
|
721
|
+
} catch (err) {
|
|
722
|
+
throw PersistenceError.createLibSecretError(err.message);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
1075
725
|
|
|
1076
|
-
|
|
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
|
-
|
|
735
|
+
async reloadNecessary(lastSync) {
|
|
736
|
+
return this.filePersistence.reloadNecessary(lastSync);
|
|
737
|
+
}
|
|
1079
738
|
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
throw PersistenceError.createLibSecretError(err.code, err.message);
|
|
1084
|
-
});
|
|
739
|
+
getFilePath() {
|
|
740
|
+
return this.filePersistence.getFilePath();
|
|
741
|
+
}
|
|
1085
742
|
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
};
|
|
743
|
+
getLogger() {
|
|
744
|
+
return this.filePersistence.getLogger();
|
|
745
|
+
}
|
|
1091
746
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
747
|
+
createForPersistenceValidation() {
|
|
748
|
+
const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
|
|
749
|
+
return LibSecretPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
|
|
750
|
+
}
|
|
1095
751
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
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
|
-
|
|
1107
|
-
|
|
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
|
-
|
|
1123
|
-
try {
|
|
1124
|
-
var _this8 = this;
|
|
820
|
+
let username = null;
|
|
1125
821
|
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
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
|
-
|
|
1133
|
-
|
|
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
|
-
|
|
1137
|
-
return this.filePersistence.getLogger();
|
|
1138
|
-
};
|
|
845
|
+
}
|
|
1139
846
|
|
|
1140
|
-
|
|
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
|