A cloud-based identity and access management service for securing user authentication and resource access
On questions 1 and 2, Microsoft doesn't document a rule about Electron/, so only Microsoft can confirm whether it's intended. What the documentation does say is consistent with your A/B result. The FIDO2 developer guidance says that for web sign-in "the availability of FIDO2 passwordless authentication … will depend on the combination of browser and platform", and the Windows column of the passkey compatibility matrix lists Chrome, Edge and Firefox. An embedded Electron browser isn't one of them, so Entra deciding from the request's User-Agent not to offer passkeys fits the documented behaviour.
Narrowing down question 2
Since you already rewrite the header for Microsoft sign-in hosts, you can test the token question directly:
Remove only your app's token and keep Electron/44.10.0.
Keep your app's token and remove only Electron/44.10.0.
To rule out other differences, log the header actually sent. session.webRequest.onBeforeSendHeaders gives you the outgoing User-Agent for login.microsoftonline.com requests. If the passkey option appears or disappears with the Electron/ token alone, include that minimal A/B result and a correlation ID in a support case.
Question 3: what to use instead
I wouldn't ship the User-Agent rewrite. It relies on undocumented classification that can change at any time. For Windows apps, Microsoft's FIDO2 developer guidance recommends, in this order: the Windows broker (WAM), then WebView2 for an embedded browser, then the system browser. For an Electron app, MSAL Node covers the two most practical options.
Option A: Windows broker (WAM). Install @azure/msal-node-extensions and register the redirect URI ms-appx-web://Microsoft.AAD.BrokerPlugin/<client-id> on the app registration. The broker is Windows-only, and MSAL Node doesn't fall back to another flow if the broker fails.
const { PublicClientApplication } = require("@azure/msal-node");
const { NativeBrokerPlugin } = require("@azure/msal-node-extensions");
const pca = new PublicClientApplication({
auth: { clientId: "<client-id>", authority: "https://login.microsoftonline.com/<tenant-id>" },
broker: { nativeBrokerPlugin: new NativeBrokerPlugin() },
});
const result = await pca.acquireTokenInteractive({
scopes: ["User.Read"],
windowHandle: mainWindow.getNativeWindowHandle(), // keeps the prompt on top of your window
});
Option B: system browser. Register http://localhost as a redirect URI under Mobile and desktop applications. acquireTokenInteractive runs the loopback listener and the PKCE exchange for you; you only open the URL: The user then signs in with their default browser. If that's Edge, Chrome or Firefox on Windows, passkeys are offered as documented, including passkeys in 1Password.
const { shell } = require("electron");
const result = await pca.acquireTokenInteractive({
scopes: ["User.Read"],
openBrowser: async (url) => { await shell.openExternal(url); },
});
I haven't run this against an Electron 44 build myself, so test both options with your tenant. The API calls are taken from the MSAL Node documentation.
If this helps, please consider marking it as the accepted answer so others can find it.