Skip to content

Commit

Permalink
Catch Dpapi Require error (#7412)
Browse files Browse the repository at this point in the history
For usages of msal-node-extensions that don't need persistance - like if
you just want to use the Broker.

We are hitting this in VS Code because we are trying to bundle our code
with Webpack... but since the require of DPAPI happens regardless of
what features you use, we get an error from locating this `.node` file,
which I have not included in our bundle.

---------

Co-authored-by: Thomas Norling <[email protected]>
  • Loading branch information
TylerLeonhardt and tnorling authored Nov 14, 2024
1 parent f810915 commit 2b750fb
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Allow requiring msal-node-extensions without Dpapi dependency",
"packageName": "@azure/msal-node-extensions",
"email": "[email protected]",
"dependentChangeType": "patch"
}
16 changes: 11 additions & 5 deletions extensions/msal-node-extensions/src/Dpapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,32 @@ export interface DpapiBindings {
): Uint8Array;
}

class defaultDpapi implements DpapiBindings {
class UnavailableDpapi implements DpapiBindings {
constructor(private readonly errorMessage: string) {}

protectData(): Uint8Array {
throw new Error("Dpapi is not supported on this platform");
throw new Error(this.errorMessage);
}
unprotectData(): Uint8Array {
throw new Error("Dpapi is not supported on this platform");
throw new Error(this.errorMessage);
}
}

let Dpapi: DpapiBindings;
if (process.platform !== "win32") {
Dpapi = new defaultDpapi();
Dpapi = new UnavailableDpapi("Dpapi is not supported on this platform");
} else {
// In .mjs files, require is not defined. We need to use createRequire to get a require function
const safeRequire =
typeof require !== "undefined"
? require
: createRequire(import.meta.url);

Dpapi = safeRequire(`../bin/${process.arch}/dpapi`);
try {
Dpapi = safeRequire(`../bin/${process.arch}/dpapi`);
} catch (e) {
Dpapi = new UnavailableDpapi("Dpapi bindings unavailable");
}
}

export { Dpapi };
16 changes: 9 additions & 7 deletions extensions/msal-node-extensions/test/dpapi-addon/Dpapi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { DataProtectionScope } from "../../src/persistence/DataProtectionScope";
import { platform } from "process";

// DPAPI is only available on windows
if (platform === "win32") {
describe("Test DPAPI addon", () => {
describe("Test DPAPI addon", () => {
if (platform === "win32") {
test("Protect and Unprotect data", () => {
const data = Buffer.from("DPAPITestString");

Expand Down Expand Up @@ -58,8 +58,10 @@ if (platform === "win32") {
);
expect(decryptedData).toEqual(data);
});
});
} else {
// Jest require that a .spec.ts file contain at least one test.
test("Empty test", () => {});
}
} else {
test("Should throw on non-Windows", () => {
const data = Buffer.from("DPAPITestString");
expect(() => Dpapi.protectData(data, null, DataProtectionScope.LocalMachine)).toThrow();
});
}
});

0 comments on commit 2b750fb

Please sign in to comment.