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