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