Skip to content

Commit 032f978

Browse files
Fall back to FilePersistence when libsecret is unavailable
On Linux without libsecret installed, PersistenceCreator.createPersistence() fails because the keytar native module cannot load libsecret-1.so.0. The usePlaintextFileOnLinux fallback in PersistenceCreator only handles verification failures, not module load failures. Catch the error in createPersistence() and fall back to FilePersistence directly, ensuring the CLI works on Linux environments without libsecret (CI, containers, headless servers). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ee567ba commit 032f978

2 files changed

Lines changed: 23 additions & 5 deletions

File tree

src/auth/msalCachePlugin.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ describe('msalCachePlugin', () => {
5151
assert.notStrictEqual(persistence, undefined);
5252
});
5353

54+
it(`falls back to FilePersistence when PersistenceCreator fails`, async () => {
55+
const msalExtensions = await import('@azure/msal-node-extensions');
56+
sinon.stub(msalExtensions.PersistenceCreator, 'createPersistence').rejects(new Error('libsecret not available'));
57+
const filePersistenceCreateStub = sinon.stub(msalExtensions.FilePersistence, 'create').resolves(mockPersistence as any);
58+
59+
const persistence = await msalCachePlugin.createPersistence();
60+
assert(filePersistenceCreateStub.calledOnce);
61+
assert.strictEqual(persistence, mockPersistence);
62+
});
63+
5464
it(`creates plugin using PersistenceCachePlugin`, async () => {
5565
const plugin = await msalCachePlugin.createPlugin(mockPersistence);
5666
assert.notStrictEqual(plugin, undefined);

src/auth/msalCachePlugin.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,19 @@ let _initPromise: Promise<{ plugin: ICachePlugin; persistence: IPersistence }> |
1717

1818
export const msalCachePlugin = {
1919
async createPersistence(): Promise<IPersistence> {
20-
const { DataProtectionScope, PersistenceCreator } = await import('@azure/msal-node-extensions');
21-
return PersistenceCreator.createPersistence({
22-
...persistenceConfiguration,
23-
dataProtectionScope: DataProtectionScope.CurrentUser
24-
});
20+
const { DataProtectionScope, FilePersistence, PersistenceCreator } = await import('@azure/msal-node-extensions');
21+
try {
22+
return await PersistenceCreator.createPersistence({
23+
...persistenceConfiguration,
24+
dataProtectionScope: DataProtectionScope.CurrentUser
25+
});
26+
}
27+
catch {
28+
// PersistenceCreator fails on Linux when libsecret is not installed
29+
// because the keytar native module cannot load. Fall back to an
30+
// unencrypted file, which matches the usePlaintextFileOnLinux intent.
31+
return FilePersistence.create(persistenceConfiguration.cachePath);
32+
}
2533
},
2634

2735
async createPlugin(persistence: IPersistence): Promise<ICachePlugin> {

0 commit comments

Comments
 (0)