@azure/msal-node-extensions 1.0.0-alpha.12 → 1.0.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,86 +1,86 @@
1
- /*
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
-
6
- import { setPassword, getPassword, deletePassword } from "keytar";
7
- import { FilePersistence } from "./FilePersistence";
8
- import { IPersistence } from "./IPersistence";
9
- import { PersistenceError } from "../error/PersistenceError";
10
- import { Logger, LoggerOptions } from "@azure/msal-common";
11
- import { dirname } from "path";
12
- import { BasePersistence } from "./BasePersistence";
13
-
14
- /**
15
- * Uses reads and writes passwords to macOS keychain
16
- *
17
- * serviceName: Identifier used as key for whatever value is stored
18
- * accountName: Account under which password should be stored
19
- */
20
- export class KeychainPersistence extends BasePersistence implements IPersistence {
21
-
22
- protected readonly serviceName;
23
- protected readonly accountName;
24
- private filePersistence: FilePersistence;
25
-
26
- private constructor(serviceName: string, accountName: string) {
27
- super();
28
- this.serviceName = serviceName;
29
- this.accountName = accountName;
30
- }
31
-
32
- public static async create(
33
- fileLocation: string,
34
- serviceName: string,
35
- accountName: string,
36
- loggerOptions?: LoggerOptions): Promise<KeychainPersistence> {
37
-
38
- const persistence = new KeychainPersistence(serviceName, accountName);
39
- persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
40
- return persistence;
41
- }
42
-
43
- public async save(contents: string): Promise<void> {
44
- try {
45
- await setPassword(this.serviceName, this.accountName, contents);
46
- } catch (err) {
47
- throw PersistenceError.createKeychainPersistenceError(err.message);
48
- }
49
- // Write dummy data to update file mtime
50
- await this.filePersistence.save("{}");
51
- }
52
-
53
- public async load(): Promise<string | null> {
54
- try{
55
- return await getPassword(this.serviceName, this.accountName);
56
- } catch(err){
57
- throw PersistenceError.createKeychainPersistenceError(err.message);
58
- }
59
- }
60
-
61
- public async delete(): Promise<boolean> {
62
- try {
63
- await this.filePersistence.delete();
64
- return await deletePassword(this.serviceName, this.accountName);
65
- } catch (err) {
66
- throw PersistenceError.createKeychainPersistenceError(err.message);
67
- }
68
- }
69
-
70
- public async reloadNecessary(lastSync: number): Promise<boolean> {
71
- return this.filePersistence.reloadNecessary(lastSync);
72
- }
73
-
74
- public getFilePath(): string {
75
- return this.filePersistence.getFilePath();
76
- }
77
-
78
- public getLogger(): Logger {
79
- return this.filePersistence.getLogger();
80
- }
81
-
82
- public createForPersistenceValidation(): Promise<KeychainPersistence> {
83
- const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
84
- return KeychainPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
85
- }
86
- }
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { setPassword, getPassword, deletePassword } from "keytar";
7
+ import { FilePersistence } from "./FilePersistence";
8
+ import { IPersistence } from "./IPersistence";
9
+ import { PersistenceError } from "../error/PersistenceError";
10
+ import { Logger, LoggerOptions } from "@azure/msal-common";
11
+ import { dirname } from "path";
12
+ import { BasePersistence } from "./BasePersistence";
13
+
14
+ /**
15
+ * Uses reads and writes passwords to macOS keychain
16
+ *
17
+ * serviceName: Identifier used as key for whatever value is stored
18
+ * accountName: Account under which password should be stored
19
+ */
20
+ export class KeychainPersistence extends BasePersistence implements IPersistence {
21
+
22
+ protected readonly serviceName;
23
+ protected readonly accountName;
24
+ private filePersistence: FilePersistence;
25
+
26
+ private constructor(serviceName: string, accountName: string) {
27
+ super();
28
+ this.serviceName = serviceName;
29
+ this.accountName = accountName;
30
+ }
31
+
32
+ public static async create(
33
+ fileLocation: string,
34
+ serviceName: string,
35
+ accountName: string,
36
+ loggerOptions?: LoggerOptions): Promise<KeychainPersistence> {
37
+
38
+ const persistence = new KeychainPersistence(serviceName, accountName);
39
+ persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
40
+ return persistence;
41
+ }
42
+
43
+ public async save(contents: string): Promise<void> {
44
+ try {
45
+ await setPassword(this.serviceName, this.accountName, contents);
46
+ } catch (err) {
47
+ throw PersistenceError.createKeychainPersistenceError(err.message);
48
+ }
49
+ // Write dummy data to update file mtime
50
+ await this.filePersistence.save("{}");
51
+ }
52
+
53
+ public async load(): Promise<string | null> {
54
+ try{
55
+ return await getPassword(this.serviceName, this.accountName);
56
+ } catch(err){
57
+ throw PersistenceError.createKeychainPersistenceError(err.message);
58
+ }
59
+ }
60
+
61
+ public async delete(): Promise<boolean> {
62
+ try {
63
+ await this.filePersistence.delete();
64
+ return await deletePassword(this.serviceName, this.accountName);
65
+ } catch (err) {
66
+ throw PersistenceError.createKeychainPersistenceError(err.message);
67
+ }
68
+ }
69
+
70
+ public async reloadNecessary(lastSync: number): Promise<boolean> {
71
+ return this.filePersistence.reloadNecessary(lastSync);
72
+ }
73
+
74
+ public getFilePath(): string {
75
+ return this.filePersistence.getFilePath();
76
+ }
77
+
78
+ public getLogger(): Logger {
79
+ return this.filePersistence.getLogger();
80
+ }
81
+
82
+ public createForPersistenceValidation(): Promise<KeychainPersistence> {
83
+ const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
84
+ return KeychainPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
85
+ }
86
+ }
@@ -1,87 +1,87 @@
1
- /*
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
-
6
- import { setPassword, getPassword, deletePassword } from "keytar";
7
- import { FilePersistence } from "./FilePersistence";
8
- import { IPersistence } from "./IPersistence";
9
- import { PersistenceError } from "../error/PersistenceError";
10
- import { Logger, LoggerOptions } from "@azure/msal-common";
11
- import { dirname } from "path";
12
- import { BasePersistence } from "./BasePersistence";
13
-
14
- /**
15
- * Uses reads and writes passwords to Secret Service API/libsecret. Requires libsecret
16
- * to be installed.
17
- *
18
- * serviceName: Identifier used as key for whatever value is stored
19
- * accountName: Account under which password should be stored
20
- */
21
- export class LibSecretPersistence extends BasePersistence implements IPersistence {
22
-
23
- protected readonly serviceName;
24
- protected readonly accountName;
25
- private filePersistence: FilePersistence;
26
-
27
- private constructor(serviceName: string, accountName: string) {
28
- super();
29
- this.serviceName = serviceName;
30
- this.accountName = accountName;
31
- }
32
-
33
- public static async create(
34
- fileLocation: string,
35
- serviceName: string,
36
- accountName: string,
37
- loggerOptions?: LoggerOptions): Promise<LibSecretPersistence> {
38
-
39
- const persistence = new LibSecretPersistence(serviceName, accountName);
40
- persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
41
- return persistence;
42
- }
43
-
44
- public async save(contents: string): Promise<void> {
45
- try {
46
- await setPassword(this.serviceName, this.accountName, contents);
47
- } catch (err) {
48
- throw PersistenceError.createLibSecretError(err.message);
49
- }
50
- // Write dummy data to update file mtime
51
- await this.filePersistence.save("{}");
52
- }
53
-
54
- public async load(): Promise<string | null> {
55
- try {
56
- return await getPassword(this.serviceName, this.accountName);
57
- } catch (err) {
58
- throw PersistenceError.createLibSecretError(err.message);
59
- }
60
- }
61
-
62
- public async delete(): Promise<boolean> {
63
- try {
64
- await this.filePersistence.delete();
65
- return await deletePassword(this.serviceName, this.accountName);
66
- } catch (err) {
67
- throw PersistenceError.createLibSecretError(err.message);
68
- }
69
- }
70
-
71
- public async reloadNecessary(lastSync: number): Promise<boolean> {
72
- return this.filePersistence.reloadNecessary(lastSync);
73
- }
74
-
75
- public getFilePath(): string {
76
- return this.filePersistence.getFilePath();
77
- }
78
-
79
- public getLogger(): Logger {
80
- return this.filePersistence.getLogger();
81
- }
82
-
83
- public createForPersistenceValidation(): Promise<LibSecretPersistence> {
84
- const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
85
- return LibSecretPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
86
- }
87
- }
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { setPassword, getPassword, deletePassword } from "keytar";
7
+ import { FilePersistence } from "./FilePersistence";
8
+ import { IPersistence } from "./IPersistence";
9
+ import { PersistenceError } from "../error/PersistenceError";
10
+ import { Logger, LoggerOptions } from "@azure/msal-common";
11
+ import { dirname } from "path";
12
+ import { BasePersistence } from "./BasePersistence";
13
+
14
+ /**
15
+ * Uses reads and writes passwords to Secret Service API/libsecret. Requires libsecret
16
+ * to be installed.
17
+ *
18
+ * serviceName: Identifier used as key for whatever value is stored
19
+ * accountName: Account under which password should be stored
20
+ */
21
+ export class LibSecretPersistence extends BasePersistence implements IPersistence {
22
+
23
+ protected readonly serviceName;
24
+ protected readonly accountName;
25
+ private filePersistence: FilePersistence;
26
+
27
+ private constructor(serviceName: string, accountName: string) {
28
+ super();
29
+ this.serviceName = serviceName;
30
+ this.accountName = accountName;
31
+ }
32
+
33
+ public static async create(
34
+ fileLocation: string,
35
+ serviceName: string,
36
+ accountName: string,
37
+ loggerOptions?: LoggerOptions): Promise<LibSecretPersistence> {
38
+
39
+ const persistence = new LibSecretPersistence(serviceName, accountName);
40
+ persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
41
+ return persistence;
42
+ }
43
+
44
+ public async save(contents: string): Promise<void> {
45
+ try {
46
+ await setPassword(this.serviceName, this.accountName, contents);
47
+ } catch (err) {
48
+ throw PersistenceError.createLibSecretError(err.message);
49
+ }
50
+ // Write dummy data to update file mtime
51
+ await this.filePersistence.save("{}");
52
+ }
53
+
54
+ public async load(): Promise<string | null> {
55
+ try {
56
+ return await getPassword(this.serviceName, this.accountName);
57
+ } catch (err) {
58
+ throw PersistenceError.createLibSecretError(err.message);
59
+ }
60
+ }
61
+
62
+ public async delete(): Promise<boolean> {
63
+ try {
64
+ await this.filePersistence.delete();
65
+ return await deletePassword(this.serviceName, this.accountName);
66
+ } catch (err) {
67
+ throw PersistenceError.createLibSecretError(err.message);
68
+ }
69
+ }
70
+
71
+ public async reloadNecessary(lastSync: number): Promise<boolean> {
72
+ return this.filePersistence.reloadNecessary(lastSync);
73
+ }
74
+
75
+ public getFilePath(): string {
76
+ return this.filePersistence.getFilePath();
77
+ }
78
+
79
+ public getLogger(): Logger {
80
+ return this.filePersistence.getLogger();
81
+ }
82
+
83
+ public createForPersistenceValidation(): Promise<LibSecretPersistence> {
84
+ const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
85
+ return LibSecretPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
86
+ }
87
+ }
@@ -1,106 +1,106 @@
1
- /*
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
-
6
- import { IPersistence } from "./IPersistence";
7
- import { CrossPlatformLock } from "../lock/CrossPlatformLock";
8
- import { CrossPlatformLockOptions } from "../lock/CrossPlatformLockOptions";
9
- import { pid } from "process";
10
- import { TokenCacheContext, ICachePlugin, Logger } from "@azure/msal-common";
11
-
12
- /**
13
- * MSAL cache plugin which enables callers to write the MSAL cache to disk on Windows,
14
- * macOs, and Linux.
15
- *
16
- * - Persistence can be one of:
17
- * - FilePersistence: Writes and reads from an unencrypted file. Can be used on Windows,
18
- * macOs, or Linux.
19
- * - FilePersistenceWithDataProtection: Used on Windows, writes and reads from file encrypted
20
- * with windows dpapi-addon.
21
- * - KeychainPersistence: Used on macOs, writes and reads from keychain.
22
- * - LibSecretPersistence: Used on linux, writes and reads from secret service API. Requires
23
- * libsecret be installed.
24
- */
25
- export class PersistenceCachePlugin implements ICachePlugin {
26
-
27
- public persistence: IPersistence;
28
- public lastSync: number;
29
- public currentCache: string;
30
- public lockFilePath: string;
31
-
32
- private crossPlatformLock: CrossPlatformLock;
33
-
34
- private logger: Logger;
35
-
36
- constructor(persistence: IPersistence, lockOptions?: CrossPlatformLockOptions) {
37
- this.persistence = persistence;
38
-
39
- // initialize logger
40
- this.logger = persistence.getLogger();
41
-
42
- // create file lock
43
- this.lockFilePath = `${this.persistence.getFilePath()}.lockfile`;
44
- this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions);
45
-
46
- // initialize default values
47
- this.lastSync = 0;
48
- this.currentCache = null;
49
- }
50
-
51
- /**
52
- * Reads from storage and saves an in-memory copy. If persistence has not been updated
53
- * since last time data was read, in memory copy is used.
54
- *
55
- * If cacheContext.cacheHasChanged === true, then file lock is created and not deleted until
56
- * afterCacheAccess() is called, to prevent the cache file from changing in between
57
- * beforeCacheAccess() and afterCacheAccess().
58
- */
59
- public async beforeCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
60
- this.logger.info("Executing before cache access");
61
- const reloadNecessary = await this.persistence.reloadNecessary(this.lastSync);
62
- if (!reloadNecessary && this.currentCache !== null) {
63
- if (cacheContext.cacheHasChanged) {
64
- this.logger.verbose("Cache context has changed");
65
- await this.crossPlatformLock.lock();
66
- }
67
- return;
68
- }
69
- try {
70
- this.logger.info(`Reload necessary. Last sync time: ${this.lastSync}`);
71
- await this.crossPlatformLock.lock();
72
-
73
- this.currentCache = await this.persistence.load();
74
- this.lastSync = new Date().getTime();
75
- cacheContext.tokenCache.deserialize(this.currentCache);
76
-
77
- this.logger.info(`Last sync time updated to: ${this.lastSync}`);
78
- } finally {
79
- if (!cacheContext.cacheHasChanged) {
80
- await this.crossPlatformLock.unlock();
81
- this.logger.info(`Pid ${pid} released lock`);
82
- } else {
83
- this.logger.info(`Pid ${pid} beforeCacheAccess did not release lock`);
84
- }
85
- }
86
- }
87
-
88
- /**
89
- * Writes to storage if MSAL in memory copy of cache has been changed.
90
- */
91
- public async afterCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
92
- this.logger.info("Executing after cache access");
93
- try {
94
- if (cacheContext.cacheHasChanged) {
95
- this.logger.info("Msal in-memory cache has changed. Writing changes to persistence");
96
- this.currentCache = cacheContext.tokenCache.serialize();
97
- await this.persistence.save(this.currentCache);
98
- } else {
99
- this.logger.info("Msal in-memory cache has not changed. Did not write to persistence");
100
- }
101
- } finally {
102
- await this.crossPlatformLock.unlock();
103
- this.logger.info(`Pid ${pid} afterCacheAccess released lock`);
104
- }
105
- }
106
- }
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { IPersistence } from "./IPersistence";
7
+ import { CrossPlatformLock } from "../lock/CrossPlatformLock";
8
+ import { CrossPlatformLockOptions } from "../lock/CrossPlatformLockOptions";
9
+ import { pid } from "process";
10
+ import { TokenCacheContext, ICachePlugin, Logger } from "@azure/msal-common";
11
+
12
+ /**
13
+ * MSAL cache plugin which enables callers to write the MSAL cache to disk on Windows,
14
+ * macOs, and Linux.
15
+ *
16
+ * - Persistence can be one of:
17
+ * - FilePersistence: Writes and reads from an unencrypted file. Can be used on Windows,
18
+ * macOs, or Linux.
19
+ * - FilePersistenceWithDataProtection: Used on Windows, writes and reads from file encrypted
20
+ * with windows dpapi-addon.
21
+ * - KeychainPersistence: Used on macOs, writes and reads from keychain.
22
+ * - LibSecretPersistence: Used on linux, writes and reads from secret service API. Requires
23
+ * libsecret be installed.
24
+ */
25
+ export class PersistenceCachePlugin implements ICachePlugin {
26
+
27
+ public persistence: IPersistence;
28
+ public lastSync: number;
29
+ public currentCache: string;
30
+ public lockFilePath: string;
31
+
32
+ private crossPlatformLock: CrossPlatformLock;
33
+
34
+ private logger: Logger;
35
+
36
+ constructor(persistence: IPersistence, lockOptions?: CrossPlatformLockOptions) {
37
+ this.persistence = persistence;
38
+
39
+ // initialize logger
40
+ this.logger = persistence.getLogger();
41
+
42
+ // create file lock
43
+ this.lockFilePath = `${this.persistence.getFilePath()}.lockfile`;
44
+ this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions);
45
+
46
+ // initialize default values
47
+ this.lastSync = 0;
48
+ this.currentCache = null;
49
+ }
50
+
51
+ /**
52
+ * Reads from storage and saves an in-memory copy. If persistence has not been updated
53
+ * since last time data was read, in memory copy is used.
54
+ *
55
+ * If cacheContext.cacheHasChanged === true, then file lock is created and not deleted until
56
+ * afterCacheAccess() is called, to prevent the cache file from changing in between
57
+ * beforeCacheAccess() and afterCacheAccess().
58
+ */
59
+ public async beforeCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
60
+ this.logger.info("Executing before cache access");
61
+ const reloadNecessary = await this.persistence.reloadNecessary(this.lastSync);
62
+ if (!reloadNecessary && this.currentCache !== null) {
63
+ if (cacheContext.cacheHasChanged) {
64
+ this.logger.verbose("Cache context has changed");
65
+ await this.crossPlatformLock.lock();
66
+ }
67
+ return;
68
+ }
69
+ try {
70
+ this.logger.info(`Reload necessary. Last sync time: ${this.lastSync}`);
71
+ await this.crossPlatformLock.lock();
72
+
73
+ this.currentCache = await this.persistence.load();
74
+ this.lastSync = new Date().getTime();
75
+ cacheContext.tokenCache.deserialize(this.currentCache);
76
+
77
+ this.logger.info(`Last sync time updated to: ${this.lastSync}`);
78
+ } finally {
79
+ if (!cacheContext.cacheHasChanged) {
80
+ await this.crossPlatformLock.unlock();
81
+ this.logger.info(`Pid ${pid} released lock`);
82
+ } else {
83
+ this.logger.info(`Pid ${pid} beforeCacheAccess did not release lock`);
84
+ }
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Writes to storage if MSAL in memory copy of cache has been changed.
90
+ */
91
+ public async afterCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
92
+ this.logger.info("Executing after cache access");
93
+ try {
94
+ if (cacheContext.cacheHasChanged) {
95
+ this.logger.info("Msal in-memory cache has changed. Writing changes to persistence");
96
+ this.currentCache = cacheContext.tokenCache.serialize();
97
+ await this.persistence.save(this.currentCache);
98
+ } else {
99
+ this.logger.info("Msal in-memory cache has not changed. Did not write to persistence");
100
+ }
101
+ } finally {
102
+ await this.crossPlatformLock.unlock();
103
+ this.logger.info(`Pid ${pid} afterCacheAccess released lock`);
104
+ }
105
+ }
106
+ }