@azure/msal-node-extensions 1.0.0-alpha.30 → 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.
@@ -10,6 +10,7 @@ var path = require('path');
10
10
  var path__default = _interopDefault(path);
11
11
  var msalCommon = require('@azure/msal-common');
12
12
  var keytar = require('keytar');
13
+ var msalNodeRuntime = require('@azure/msal-node-runtime');
13
14
 
14
15
  /*
15
16
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -20,35 +21,29 @@ const Constants = {
20
21
  * An existing file was the target of an operation that required that the target not exist
21
22
  */
22
23
  EEXIST_ERROR: "EEXIST",
23
-
24
24
  /**
25
25
  * No such file or directory: Commonly raised by fs operations to indicate that a component
26
26
  * of the specified pathname does not exist. No entity (file or directory) could be found
27
27
  * by the given path
28
28
  */
29
29
  ENOENT_ERROR: "ENOENT",
30
-
31
30
  /**
32
31
  * Operation not permitted. An attempt was made to perform an operation that requires
33
32
  * elevated privileges.
34
33
  */
35
34
  EPERM_ERROR: "EPERM",
36
-
37
35
  /**
38
36
  * Default service name for using MSAL Keytar
39
37
  */
40
38
  DEFAULT_SERVICE_NAME: "msal-node-extensions",
41
-
42
39
  /**
43
40
  * Test data used to verify underlying persistence mechanism
44
41
  */
45
42
  PERSISTENCE_TEST_DATA: "Dummy data to verify underlying persistence mechanism",
46
-
47
43
  /**
48
44
  * This is the value of a the guid if the process is being ran by the root user
49
45
  */
50
46
  LINUX_ROOT_USER_GUID: 0,
51
-
52
47
  /**
53
48
  * List of environment variables
54
49
  */
@@ -65,18 +60,21 @@ const Constants = {
65
60
  DEFAULT_CACHE_FILE_NAME: "cache.json"
66
61
  };
67
62
  var Platform;
68
-
69
63
  (function (Platform) {
70
64
  Platform["WINDOWS"] = "win32";
71
65
  Platform["LINUX"] = "linux";
72
66
  Platform["MACOS"] = "darwin";
73
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 = {}));
74
73
 
75
74
  /*
76
75
  * Copyright (c) Microsoft Corporation. All rights reserved.
77
76
  * Licensed under the MIT License.
78
77
  */
79
-
80
78
  /**
81
79
  * Error thrown when trying to write MSAL cache to persistence.
82
80
  */
@@ -92,8 +90,6 @@ class PersistenceError extends Error {
92
90
  /**
93
91
  * Error thrown when trying to access the file system.
94
92
  */
95
-
96
-
97
93
  static createFileSystemError(errorCode, errorMessage) {
98
94
  return new PersistenceError(errorCode, errorMessage);
99
95
  }
@@ -101,32 +97,24 @@ class PersistenceError extends Error {
101
97
  * Error thrown when trying to write, load, or delete data from secret service on linux.
102
98
  * Libsecret is used to access secret service.
103
99
  */
104
-
105
-
106
100
  static createLibSecretError(errorMessage) {
107
101
  return new PersistenceError("GnomeKeyringError", errorMessage);
108
102
  }
109
103
  /**
110
104
  * Error thrown when trying to write, load, or delete data from keychain on macOs.
111
105
  */
112
-
113
-
114
106
  static createKeychainPersistenceError(errorMessage) {
115
107
  return new PersistenceError("KeychainError", errorMessage);
116
108
  }
117
109
  /**
118
110
  * Error thrown when trying to encrypt or decrypt data using DPAPI on Windows.
119
111
  */
120
-
121
-
122
112
  static createFilePersistenceWithDPAPIError(errorMessage) {
123
113
  return new PersistenceError("DPAPIEncryptedFileError", errorMessage);
124
114
  }
125
115
  /**
126
116
  * Error thrown when using the cross platform lock.
127
117
  */
128
-
129
-
130
118
  static createCrossPlatformLockError(errorMessage) {
131
119
  return new PersistenceError("CrossPlatformLockError", errorMessage);
132
120
  }
@@ -136,8 +124,6 @@ class PersistenceError extends Error {
136
124
  * @param errorMessage string
137
125
  * @returns PersistenceError
138
126
  */
139
-
140
-
141
127
  static createCachePersistenceError(errorMessage) {
142
128
  return new PersistenceError("CachePersistenceError", errorMessage);
143
129
  }
@@ -147,8 +133,6 @@ class PersistenceError extends Error {
147
133
  * @param errorMessage string
148
134
  * @returns PersistenceError
149
135
  */
150
-
151
-
152
136
  static createNotSupportedError(errorMessage) {
153
137
  return new PersistenceError("NotSupportedError", errorMessage);
154
138
  }
@@ -158,8 +142,6 @@ class PersistenceError extends Error {
158
142
  * @param errorMessage string
159
143
  * @returns PersistenceError
160
144
  */
161
-
162
-
163
145
  static createPersistenceNotVerifiedError(errorMessage) {
164
146
  return new PersistenceError("PersistenceNotVerifiedError", errorMessage);
165
147
  }
@@ -169,12 +151,9 @@ class PersistenceError extends Error {
169
151
  * @param errorMessage string
170
152
  * @returns PersistenceError
171
153
  */
172
-
173
-
174
154
  static createPersistenceNotValidatedError(errorMessage) {
175
155
  return new PersistenceError("PersistenceNotValidatedError", errorMessage);
176
156
  }
177
-
178
157
  }
179
158
 
180
159
  /*
@@ -184,7 +163,6 @@ class PersistenceError extends Error {
184
163
  /**
185
164
  * Cross-process lock that works on all platforms.
186
165
  */
187
-
188
166
  class CrossPlatformLock {
189
167
  constructor(lockFilePath, logger, lockOptions) {
190
168
  this.lockFilePath = lockFilePath;
@@ -197,8 +175,6 @@ class CrossPlatformLock {
197
175
  * cache file but with .lockfile extension. If another process has already created
198
176
  * the lockfile, will back off and retry based on configuration settings set by CrossPlatformLockOptions
199
177
  */
200
-
201
-
202
178
  async lock() {
203
179
  for (let tryCount = 0; tryCount < this.retryNumber; tryCount++) {
204
180
  try {
@@ -217,15 +193,12 @@ class CrossPlatformLock {
217
193
  }
218
194
  }
219
195
  }
220
-
221
196
  this.logger.error(`${process$1.pid} was not able to acquire lock. Exceeded amount of retries set in the options`);
222
197
  throw PersistenceError.createCrossPlatformLockError("Not able to acquire lock. Exceeded amount of retries set in options");
223
198
  }
224
199
  /**
225
200
  * unlocks cache file by deleting .lockfile.
226
201
  */
227
-
228
-
229
202
  async unlock() {
230
203
  try {
231
204
  if (this.lockFileHandle) {
@@ -245,13 +218,11 @@ class CrossPlatformLock {
245
218
  }
246
219
  }
247
220
  }
248
-
249
221
  sleep(ms) {
250
222
  return new Promise(resolve => {
251
223
  setTimeout(resolve, ms);
252
224
  });
253
225
  }
254
-
255
226
  }
256
227
 
257
228
  /*
@@ -271,16 +242,15 @@ class CrossPlatformLock {
271
242
  * - LibSecretPersistence: Used on linux, writes and reads from secret service API. Requires
272
243
  * libsecret be installed.
273
244
  */
274
-
275
245
  class PersistenceCachePlugin {
276
246
  constructor(persistence, lockOptions) {
277
- this.persistence = persistence; // initialize logger
278
-
279
- this.logger = persistence.getLogger(); // create file lock
280
-
247
+ this.persistence = persistence;
248
+ // initialize logger
249
+ this.logger = persistence.getLogger();
250
+ // create file lock
281
251
  this.lockFilePath = `${this.persistence.getFilePath()}.lockfile`;
282
- this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions); // initialize default values
283
-
252
+ this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions);
253
+ // initialize default values
284
254
  this.lastSync = 0;
285
255
  this.currentCache = null;
286
256
  }
@@ -292,21 +262,16 @@ class PersistenceCachePlugin {
292
262
  * afterCacheAccess() is called, to prevent the cache file from changing in between
293
263
  * beforeCacheAccess() and afterCacheAccess().
294
264
  */
295
-
296
-
297
265
  async beforeCacheAccess(cacheContext) {
298
266
  this.logger.info("Executing before cache access");
299
267
  const reloadNecessary = await this.persistence.reloadNecessary(this.lastSync);
300
-
301
268
  if (!reloadNecessary && this.currentCache !== null) {
302
269
  if (cacheContext.cacheHasChanged) {
303
270
  this.logger.verbose("Cache context has changed");
304
271
  await this.crossPlatformLock.lock();
305
272
  }
306
-
307
273
  return;
308
274
  }
309
-
310
275
  try {
311
276
  this.logger.info(`Reload necessary. Last sync time: ${this.lastSync}`);
312
277
  await this.crossPlatformLock.lock();
@@ -326,11 +291,8 @@ class PersistenceCachePlugin {
326
291
  /**
327
292
  * Writes to storage if MSAL in memory copy of cache has been changed.
328
293
  */
329
-
330
-
331
294
  async afterCacheAccess(cacheContext) {
332
295
  this.logger.info("Executing after cache access");
333
-
334
296
  try {
335
297
  if (cacheContext.cacheHasChanged) {
336
298
  this.logger.info("Msal in-memory cache has changed. Writing changes to persistence");
@@ -344,7 +306,6 @@ class PersistenceCachePlugin {
344
306
  this.logger.info(`Pid ${process$1.pid} afterCacheAccess released lock`);
345
307
  }
346
308
  }
347
-
348
309
  }
349
310
 
350
311
  /*
@@ -355,28 +316,23 @@ class BasePersistence {
355
316
  async verifyPersistence() {
356
317
  // We are using a different location for the test to avoid overriding the functional cache
357
318
  const persistenceValidator = await this.createForPersistenceValidation();
358
-
359
319
  try {
360
320
  await persistenceValidator.save(Constants.PERSISTENCE_TEST_DATA);
361
321
  const retrievedDummyData = await persistenceValidator.load();
362
-
363
322
  if (!retrievedDummyData) {
364
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 \
365
324
  because it cannot be started over SSH.");
366
325
  }
367
-
368
326
  if (retrievedDummyData !== Constants.PERSISTENCE_TEST_DATA) {
369
327
  throw PersistenceError.createCachePersistenceError(`Persistence check failed. Data written ${Constants.PERSISTENCE_TEST_DATA} is different \
370
328
  from data read ${retrievedDummyData}`);
371
329
  }
372
-
373
330
  await persistenceValidator.delete();
374
331
  return true;
375
332
  } catch (e) {
376
333
  throw PersistenceError.createCachePersistenceError(`Verifing persistence failed with the error: ${e}`);
377
334
  }
378
335
  }
379
-
380
336
  }
381
337
 
382
338
  /*
@@ -390,7 +346,6 @@ class BasePersistence {
390
346
  * If file or directory has not been created, it FilePersistence.create() will create
391
347
  * file and any directories in the path recursively.
392
348
  */
393
-
394
349
  class FilePersistence extends BasePersistence {
395
350
  static async create(fileLocation, loggerOptions) {
396
351
  const filePersistence = new FilePersistence();
@@ -399,7 +354,6 @@ class FilePersistence extends BasePersistence {
399
354
  await filePersistence.createCacheFile();
400
355
  return filePersistence;
401
356
  }
402
-
403
357
  async save(contents) {
404
358
  try {
405
359
  await fs.promises.writeFile(this.getFilePath(), contents, "utf-8");
@@ -407,7 +361,6 @@ class FilePersistence extends BasePersistence {
407
361
  throw PersistenceError.createFileSystemError(err.code, err.message);
408
362
  }
409
363
  }
410
-
411
364
  async saveBuffer(contents) {
412
365
  try {
413
366
  await fs.promises.writeFile(this.getFilePath(), contents);
@@ -415,7 +368,6 @@ class FilePersistence extends BasePersistence {
415
368
  throw PersistenceError.createFileSystemError(err.code, err.message);
416
369
  }
417
370
  }
418
-
419
371
  async load() {
420
372
  try {
421
373
  return await fs.promises.readFile(this.getFilePath(), "utf-8");
@@ -423,7 +375,6 @@ class FilePersistence extends BasePersistence {
423
375
  throw PersistenceError.createFileSystemError(err.code, err.message);
424
376
  }
425
377
  }
426
-
427
378
  async loadBuffer() {
428
379
  try {
429
380
  return await fs.promises.readFile(this.getFilePath());
@@ -431,7 +382,6 @@ class FilePersistence extends BasePersistence {
431
382
  throw PersistenceError.createFileSystemError(err.code, err.message);
432
383
  }
433
384
  }
434
-
435
385
  async delete() {
436
386
  try {
437
387
  await fs.promises.unlink(this.getFilePath());
@@ -442,37 +392,31 @@ class FilePersistence extends BasePersistence {
442
392
  this.logger.warning("Cache file does not exist, so it could not be deleted");
443
393
  return false;
444
394
  }
445
-
446
395
  throw PersistenceError.createFileSystemError(err.code, err.message);
447
396
  }
448
397
  }
449
-
450
398
  getFilePath() {
451
399
  return this.filePath;
452
400
  }
453
-
454
401
  async reloadNecessary(lastSync) {
455
402
  return lastSync < (await this.timeLastModified());
456
403
  }
457
-
458
404
  getLogger() {
459
405
  return this.logger;
460
406
  }
461
-
462
407
  createForPersistenceValidation() {
463
408
  const testCacheFileLocation = `${path.dirname(this.filePath)}/test.cache`;
464
409
  return FilePersistence.create(testCacheFileLocation);
465
410
  }
466
-
467
411
  static createDefaultLoggerOptions() {
468
412
  return {
469
- loggerCallback: () => {// allow users to not set loggerCallback
413
+ loggerCallback: () => {
414
+ // allow users to not set loggerCallback
470
415
  },
471
416
  piiLoggingEnabled: false,
472
417
  logLevel: msalCommon.LogLevel.Info
473
418
  };
474
419
  }
475
-
476
420
  async timeLastModified() {
477
421
  try {
478
422
  const stats = await fs.promises.stat(this.filePath);
@@ -483,19 +427,16 @@ class FilePersistence extends BasePersistence {
483
427
  this.logger.verbose("Cache file does not exist");
484
428
  return 0;
485
429
  }
486
-
487
430
  throw PersistenceError.createFileSystemError(err.code, err.message);
488
431
  }
489
432
  }
490
-
491
433
  async createCacheFile() {
492
- await this.createFileDirectory(); // File is created only if it does not exist
493
-
434
+ await this.createFileDirectory();
435
+ // File is created only if it does not exist
494
436
  const fileHandle = await fs.promises.open(this.filePath, "a");
495
437
  await fileHandle.close();
496
438
  this.logger.info(`File created at ${this.filePath}`);
497
439
  }
498
-
499
440
  async createFileDirectory() {
500
441
  try {
501
442
  await fs.promises.mkdir(path.dirname(this.filePath), {
@@ -509,14 +450,12 @@ class FilePersistence extends BasePersistence {
509
450
  }
510
451
  }
511
452
  }
512
-
513
453
  }
514
454
 
515
455
  /*
516
456
  * Copyright (c) Microsoft Corporation. All rights reserved.
517
457
  * Licensed under the MIT License.
518
458
  */
519
-
520
459
  /* eslint-disable-next-line @typescript-eslint/no-var-requires, no-var, import/no-commonjs */
521
460
  var Dpapi = /*#__PURE__*/require("../build/Release/dpapi.node");
522
461
 
@@ -524,7 +463,6 @@ var Dpapi = /*#__PURE__*/require("../build/Release/dpapi.node");
524
463
  * Copyright (c) Microsoft Corporation. All rights reserved.
525
464
  * Licensed under the MIT License.
526
465
  */
527
-
528
466
  (function (DataProtectionScope) {
529
467
  DataProtectionScope["CurrentUser"] = "CurrentUser";
530
468
  DataProtectionScope["LocalMachine"] = "LocalMachine";
@@ -540,20 +478,17 @@ var Dpapi = /*#__PURE__*/require("../build/Release/dpapi.node");
540
478
  * scope: Scope of the data protection. Either local user or the current machine
541
479
  * optionalEntropy: Password or other additional entropy used to encrypt the data
542
480
  */
543
-
544
481
  class FilePersistenceWithDataProtection extends BasePersistence {
545
482
  constructor(scope, optionalEntropy) {
546
483
  super();
547
484
  this.scope = scope;
548
485
  this.optionalEntropy = optionalEntropy ? Buffer.from(optionalEntropy, "utf-8") : null;
549
486
  }
550
-
551
487
  static async create(fileLocation, scope, optionalEntropy, loggerOptions) {
552
488
  const persistence = new FilePersistenceWithDataProtection(scope, optionalEntropy);
553
489
  persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
554
490
  return persistence;
555
491
  }
556
-
557
492
  async save(contents) {
558
493
  try {
559
494
  const encryptedContents = Dpapi.protectData(Buffer.from(contents, "utf-8"), this.optionalEntropy, this.scope.toString());
@@ -562,43 +497,34 @@ class FilePersistenceWithDataProtection extends BasePersistence {
562
497
  throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
563
498
  }
564
499
  }
565
-
566
500
  async load() {
567
501
  try {
568
502
  const encryptedContents = await this.filePersistence.loadBuffer();
569
-
570
503
  if (typeof encryptedContents === "undefined" || !encryptedContents || 0 === encryptedContents.length) {
571
504
  this.filePersistence.getLogger().info("Encrypted contents loaded from file were null or empty");
572
505
  return null;
573
506
  }
574
-
575
507
  return Dpapi.unprotectData(encryptedContents, this.optionalEntropy, this.scope.toString()).toString();
576
508
  } catch (err) {
577
509
  throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
578
510
  }
579
511
  }
580
-
581
512
  async delete() {
582
513
  return this.filePersistence.delete();
583
514
  }
584
-
585
515
  async reloadNecessary(lastSync) {
586
516
  return this.filePersistence.reloadNecessary(lastSync);
587
517
  }
588
-
589
518
  getFilePath() {
590
519
  return this.filePersistence.getFilePath();
591
520
  }
592
-
593
521
  getLogger() {
594
522
  return this.filePersistence.getLogger();
595
523
  }
596
-
597
524
  createForPersistenceValidation() {
598
525
  const testCacheFileLocation = `${path.dirname(this.filePersistence.getFilePath())}/test.cache`;
599
526
  return FilePersistenceWithDataProtection.create(testCacheFileLocation, exports.DataProtectionScope.CurrentUser);
600
527
  }
601
-
602
528
  }
603
529
 
604
530
  /*
@@ -611,31 +537,26 @@ class FilePersistenceWithDataProtection extends BasePersistence {
611
537
  * serviceName: Identifier used as key for whatever value is stored
612
538
  * accountName: Account under which password should be stored
613
539
  */
614
-
615
540
  class KeychainPersistence extends BasePersistence {
616
541
  constructor(serviceName, accountName) {
617
542
  super();
618
543
  this.serviceName = serviceName;
619
544
  this.accountName = accountName;
620
545
  }
621
-
622
546
  static async create(fileLocation, serviceName, accountName, loggerOptions) {
623
547
  const persistence = new KeychainPersistence(serviceName, accountName);
624
548
  persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
625
549
  return persistence;
626
550
  }
627
-
628
551
  async save(contents) {
629
552
  try {
630
553
  await keytar.setPassword(this.serviceName, this.accountName, contents);
631
554
  } catch (err) {
632
555
  throw PersistenceError.createKeychainPersistenceError(err.message);
633
- } // Write dummy data to update file mtime
634
-
635
-
556
+ }
557
+ // Write dummy data to update file mtime
636
558
  await this.filePersistence.save("{}");
637
559
  }
638
-
639
560
  async load() {
640
561
  try {
641
562
  return await keytar.getPassword(this.serviceName, this.accountName);
@@ -643,7 +564,6 @@ class KeychainPersistence extends BasePersistence {
643
564
  throw PersistenceError.createKeychainPersistenceError(err.message);
644
565
  }
645
566
  }
646
-
647
567
  async delete() {
648
568
  try {
649
569
  await this.filePersistence.delete();
@@ -652,24 +572,19 @@ class KeychainPersistence extends BasePersistence {
652
572
  throw PersistenceError.createKeychainPersistenceError(err.message);
653
573
  }
654
574
  }
655
-
656
575
  async reloadNecessary(lastSync) {
657
576
  return this.filePersistence.reloadNecessary(lastSync);
658
577
  }
659
-
660
578
  getFilePath() {
661
579
  return this.filePersistence.getFilePath();
662
580
  }
663
-
664
581
  getLogger() {
665
582
  return this.filePersistence.getLogger();
666
583
  }
667
-
668
584
  createForPersistenceValidation() {
669
585
  const testCacheFileLocation = `${path.dirname(this.filePersistence.getFilePath())}/test.cache`;
670
586
  return KeychainPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
671
587
  }
672
-
673
588
  }
674
589
 
675
590
  /*
@@ -683,31 +598,26 @@ class KeychainPersistence extends BasePersistence {
683
598
  * serviceName: Identifier used as key for whatever value is stored
684
599
  * accountName: Account under which password should be stored
685
600
  */
686
-
687
601
  class LibSecretPersistence extends BasePersistence {
688
602
  constructor(serviceName, accountName) {
689
603
  super();
690
604
  this.serviceName = serviceName;
691
605
  this.accountName = accountName;
692
606
  }
693
-
694
607
  static async create(fileLocation, serviceName, accountName, loggerOptions) {
695
608
  const persistence = new LibSecretPersistence(serviceName, accountName);
696
609
  persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
697
610
  return persistence;
698
611
  }
699
-
700
612
  async save(contents) {
701
613
  try {
702
614
  await keytar.setPassword(this.serviceName, this.accountName, contents);
703
615
  } catch (err) {
704
616
  throw PersistenceError.createLibSecretError(err.message);
705
- } // Write dummy data to update file mtime
706
-
707
-
617
+ }
618
+ // Write dummy data to update file mtime
708
619
  await this.filePersistence.save("{}");
709
620
  }
710
-
711
621
  async load() {
712
622
  try {
713
623
  return await keytar.getPassword(this.serviceName, this.accountName);
@@ -715,7 +625,6 @@ class LibSecretPersistence extends BasePersistence {
715
625
  throw PersistenceError.createLibSecretError(err.message);
716
626
  }
717
627
  }
718
-
719
628
  async delete() {
720
629
  try {
721
630
  await this.filePersistence.delete();
@@ -724,24 +633,19 @@ class LibSecretPersistence extends BasePersistence {
724
633
  throw PersistenceError.createLibSecretError(err.message);
725
634
  }
726
635
  }
727
-
728
636
  async reloadNecessary(lastSync) {
729
637
  return this.filePersistence.reloadNecessary(lastSync);
730
638
  }
731
-
732
639
  getFilePath() {
733
640
  return this.filePersistence.getFilePath();
734
641
  }
735
-
736
642
  getLogger() {
737
643
  return this.filePersistence.getLogger();
738
644
  }
739
-
740
645
  createForPersistenceValidation() {
741
646
  const testCacheFileLocation = `${path.dirname(this.filePersistence.getFilePath())}/test.cache`;
742
647
  return LibSecretPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
743
648
  }
744
-
745
649
  }
746
650
 
747
651
  /*
@@ -752,66 +656,50 @@ class Environment {
752
656
  static get homeEnvVar() {
753
657
  return this.getEnvironmentVariable(Constants.ENVIRONMENT.HOME);
754
658
  }
755
-
756
659
  static get lognameEnvVar() {
757
660
  return this.getEnvironmentVariable(Constants.ENVIRONMENT.LOGNAME);
758
661
  }
759
-
760
662
  static get userEnvVar() {
761
663
  return this.getEnvironmentVariable(Constants.ENVIRONMENT.USER);
762
664
  }
763
-
764
665
  static get lnameEnvVar() {
765
666
  return this.getEnvironmentVariable(Constants.ENVIRONMENT.LNAME);
766
667
  }
767
-
768
668
  static get usernameEnvVar() {
769
669
  return this.getEnvironmentVariable(Constants.ENVIRONMENT.USERNAME);
770
670
  }
771
-
772
671
  static getEnvironmentVariable(name) {
773
672
  return process.env[name];
774
673
  }
775
-
776
674
  static getEnvironmentPlatform() {
777
675
  return process.platform;
778
676
  }
779
-
780
677
  static isWindowsPlatform() {
781
678
  return this.getEnvironmentPlatform() === Platform.WINDOWS;
782
679
  }
783
-
784
680
  static isLinuxPlatform() {
785
681
  return this.getEnvironmentPlatform() === Platform.LINUX;
786
682
  }
787
-
788
683
  static isMacPlatform() {
789
684
  return this.getEnvironmentPlatform() === Platform.MACOS;
790
685
  }
791
-
792
686
  static isLinuxRootUser() {
793
687
  return process.getuid() === Constants.LINUX_ROOT_USER_GUID;
794
688
  }
795
-
796
689
  static getUserRootDirectory() {
797
690
  return !this.isWindowsPlatform ? this.getUserHomeDirOnUnix() : this.getUserHomeDirOnWindows();
798
691
  }
799
-
800
692
  static getUserHomeDirOnWindows() {
801
693
  return this.getEnvironmentVariable(Constants.ENVIRONMENT.LOCAL_APPLICATION_DATA);
802
694
  }
803
-
804
695
  static getUserHomeDirOnUnix() {
805
696
  if (this.isWindowsPlatform()) {
806
697
  throw PersistenceError.createNotSupportedError("Getting the user home directory for unix is not supported in windows");
807
698
  }
808
-
809
699
  if (!msalCommon.StringUtils.isEmpty(this.homeEnvVar)) {
810
700
  return this.homeEnvVar;
811
701
  }
812
-
813
702
  let username = null;
814
-
815
703
  if (!msalCommon.StringUtils.isEmpty(this.lognameEnvVar)) {
816
704
  username = this.lognameEnvVar;
817
705
  } else if (!msalCommon.StringUtils.isEmpty(this.userEnvVar)) {
@@ -821,7 +709,6 @@ class Environment {
821
709
  } else if (!msalCommon.StringUtils.isEmpty(this.usernameEnvVar)) {
822
710
  username = this.usernameEnvVar;
823
711
  }
824
-
825
712
  if (this.isMacPlatform()) {
826
713
  return !msalCommon.StringUtils.isEmpty(username) ? path__default.join("/Users", username) : null;
827
714
  } else if (this.isLinuxPlatform()) {
@@ -834,7 +721,6 @@ class Environment {
834
721
  throw PersistenceError.createNotSupportedError("Getting the user home directory for unix is not supported in windows");
835
722
  }
836
723
  }
837
-
838
724
  }
839
725
 
840
726
  /*
@@ -843,55 +729,441 @@ class Environment {
843
729
  */
844
730
  class PersistenceCreator {
845
731
  static async createPersistence(config) {
846
- let peristence; // On Windows, uses a DPAPI encrypted file
847
-
732
+ let peristence;
733
+ // On Windows, uses a DPAPI encrypted file
848
734
  if (Environment.isWindowsPlatform()) {
849
735
  if (!config.cachePath || !config.dataProtectionScope) {
850
736
  throw PersistenceError.createPersistenceNotValidatedError("Cache path and/or data protection scope not provided for the FilePersistenceWithDataProtection cache plugin");
851
737
  }
852
-
853
738
  peristence = await FilePersistenceWithDataProtection.create(config.cachePath, exports.DataProtectionScope.CurrentUser, undefined, config.loggerOptions);
854
- } // On Mac, uses keychain.
739
+ }
740
+ // On Mac, uses keychain.
855
741
  else if (Environment.isMacPlatform()) {
856
- if (!config.cachePath || !config.serviceName || !config.accountName) {
857
- throw PersistenceError.createPersistenceNotValidatedError("Cache path, service name and/or account name not provided for the KeychainPersistence cache plugin");
858
- }
859
-
860
- peristence = await KeychainPersistence.create(config.cachePath, config.serviceName, config.accountName, config.loggerOptions);
861
- } // On Linux, uses libsecret to store to secret service. Libsecret has to be installed.
862
- else if (Environment.isLinuxPlatform()) {
863
- if (!config.cachePath || !config.serviceName || !config.accountName) {
864
- throw PersistenceError.createPersistenceNotValidatedError("Cache path, service name and/or account name not provided for the LibSecretPersistence cache plugin");
865
- }
866
-
867
- peristence = await LibSecretPersistence.create(config.cachePath, config.serviceName, config.accountName, config.loggerOptions);
868
- } else {
869
- throw PersistenceError.createNotSupportedError("The current environment is not supported by msal-node-extensions yet.");
870
- } // Initially suppress the error thrown during persistence verification to allow us to fallback to plain text
871
-
872
-
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
873
757
  const isPersistenceVerified = await peristence.verifyPersistence().catch(() => false);
874
-
875
758
  if (!isPersistenceVerified) {
876
759
  if (Environment.isLinuxPlatform() && config.usePlaintextFileOnLinux) {
877
760
  if (!config.cachePath) {
878
761
  throw PersistenceError.createPersistenceNotValidatedError("Cache path not provided for the FilePersistence cache plugin");
879
762
  }
880
-
881
763
  peristence = await FilePersistence.create(config.cachePath, config.loggerOptions);
882
764
  const isFilePersistenceVerified = await peristence.verifyPersistence();
883
-
884
765
  if (isFilePersistenceVerified) {
885
766
  return peristence;
886
767
  }
887
768
  }
888
-
889
769
  throw PersistenceError.createPersistenceNotVerifiedError("Persistence could not be verified");
890
770
  }
891
-
892
771
  return peristence;
893
772
  }
773
+ }
774
+
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
+ }
894
788
 
789
+ /* eslint-disable header/header */
790
+ const name = "@azure/msal-node-extensions";
791
+ const version = "1.0.0-alpha.31";
792
+
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
+ };
863
+ try {
864
+ msalNodeRuntime.msalNodeRuntime.RegisterLogger(logCallback, loggerOptions.piiLoggingEnabled);
865
+ } catch (e) {
866
+ const wrappedError = this.wrapError(e);
867
+ if (wrappedError) {
868
+ throw wrappedError;
869
+ }
870
+ }
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();
1058
+ try {
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]);
1075
+ });
1076
+ }
1077
+ } catch (e) {
1078
+ const wrappedError = this.wrapError(e);
1079
+ if (wrappedError) {
1080
+ throw wrappedError;
1081
+ }
1082
+ }
1083
+ return authParams;
1084
+ }
1085
+ getAuthenticationResult(request, authResult) {
1086
+ this.logger.trace("NativeBrokerPlugin - getAuthenticationResult called", request.correlationId);
1087
+ let fromCache;
1088
+ try {
1089
+ const telemetryJSON = JSON.parse(authResult.telemetryData);
1090
+ fromCache = !!telemetryJSON["is_cache"];
1091
+ } catch (e) {
1092
+ this.logger.error("NativeBrokerPlugin: getAuthenticationResult - Error parsing telemetry data. Could not determine if response came from cache.", request.correlationId);
1093
+ }
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
+ }
895
1167
  }
896
1168
 
897
1169
  exports.Environment = Environment;
@@ -899,6 +1171,7 @@ exports.FilePersistence = FilePersistence;
899
1171
  exports.FilePersistenceWithDataProtection = FilePersistenceWithDataProtection;
900
1172
  exports.KeychainPersistence = KeychainPersistence;
901
1173
  exports.LibSecretPersistence = LibSecretPersistence;
1174
+ exports.NativeBrokerPlugin = NativeBrokerPlugin;
902
1175
  exports.PersistenceCachePlugin = PersistenceCachePlugin;
903
1176
  exports.PersistenceCreator = PersistenceCreator;
904
1177
  //# sourceMappingURL=msal-node-extensions.cjs.development.js.map