Silent, brokered authentication on Windows with the Azure Identity libraries

Scott Addie

Bill Wert

As previously announced in December 2023, the Azure Identity client libraries for .NET, Java, JavaScript, and Python include support for Web Account Manager (WAM). To recap, WAM:

  • Is the system authentication broker for Windows.
  • Offers a secure approach to acquire and refresh tokens issued by Microsoft Entra ID.
  • Can be used via the .NET, Java, and JavaScript libraries’ InteractiveBrowserCredential type; for Python, the InteractiveBrowserBrokerCredential type is used.

The team reflected on the existing authentication experience—more specifically, the possibility of suppressing the modal account picker dialog that supports interactively logging in. There are, after all, many customers who always sign into Windows with the same default user account and therefore only ever want to authenticate using that account. Forcing this cohort to repeatedly select their sole account from an account picker is aggravating.

Today, we’re pleased to announce that silently authenticating the platform-specific default account via WAM is possible.

Authenticate the default system account via WAM

You can opt into attempting to sign in automatically with whatever the broker thinks is the default system account. In the context of Windows, that default system account is the signed-in user. As a prerequisite, use a version of the broker package that supports this feature.

Ecosystem Package Minimum package version
.NET Azure.Identity.Broker 1.1.0
Java azure-identity-broker 1.1.0
JavaScript @azure/identity-broker 1.0.0†
Python azure-identity-broker 1.1.0
† For JavaScript, update your @azure/identity dependency to version 4.1.0 or later. There’s no need to update the broker package to use this feature.

To opt in, see the ecosystem-specific guidance in the following sections.

.NET

Set InteractiveBrowserCredentialBrokerOptionsUseDefaultBrokerAccount property to true:

using Azure.Identity;
using Azure.Identity.Broker;

// code omitted for brevity

IntPtr windowHandle = GetForegroundWindow();
InteractiveBrowserCredential credential = new(
    new InteractiveBrowserCredentialBrokerOptions(windowHandle)
    {
        UseDefaultBrokerAccount = true,
    });
);

Java

Invoke the useDefaultBrokerAccount method on the InteractiveBrowserBrokerCredentialBuilder object:

import com.azure.identity.InteractiveBrowserCredential;
import com.azure.identity.broker.InteractiveBrowserBrokerCredentialBuilder;

// code omitted for brevity

long windowHandle = getWindowHandle();
InteractiveBrowserCredential credential = 
    new InteractiveBrowserBrokerCredentialBuilder()
        .useDefaultBrokerAccount()
        .setWindowHandle(windowHandle)
        .build();

JavaScript

In the brokerOptions object, set the useDefaultBrokerAccount property to true:

import { nativeBrokerPlugin } from "@azure/identity-broker";
import { 
    useIdentityPlugin,
    InteractiveBrowserCredential,
} from "@azure/identity";

useIdentityPlugin(nativeBrokerPlugin);

// code omitted for brevity

let windowHandle = getWindowHandle();

const credential = new InteractiveBrowserCredential({
    brokerOptions: {
        enabled: true,
        parentWindowHandle: windowHandle,
        useDefaultBrokerAccount: true,
    },
});

Python

Set InteractiveBrowserBrokerCredential‘s use_default_broker_account argument to True:

import win32gui
from azure.identity.broker import InteractiveBrowserBrokerCredential

# code omitted for brevity

window_handle = win32gui.GetForegroundWindow()

credential = InteractiveBrowserBrokerCredential(
    parent_window_handle=window_handle,
    use_default_broker_account=True
)

Once you opt into this behavior, the credential type attempts to sign in by asking the underlying Microsoft Authentication Library (MSAL) to perform the sign-in for the default system account. If the sign-in fails, the credential type falls back to displaying the account picker dialog, from which the user can select the appropriate account.

Comparison of authentication experiences

To better understand the differences in interactive versus silent authentication flows, let’s enable logging of events emitted only from the Azure Identity library. This logs filtering technique eliminates noise by writing messages only from the Azure-Identity event source. Let’s iterate on the WinForms and C# example from the previous blog post:

using Azure;
using Azure.Core;
using Azure.Core.Diagnostics;
using Azure.Identity;
using Azure.Identity.Broker;
using Azure.Monitor.Query;
using Azure.Monitor.Query.Models;
using System.Diagnostics.Tracing;

// code omitted for brevity

using AzureEventSourceListener listener = new((args, message) =>
{
    if (args.EventSource.Name == "Azure-Identity")
    {
        Console.WriteLine(message);
    }
}, EventLevel.LogAlways);

InteractiveBrowserCredential credential = new(
    new InteractiveBrowserCredentialBrokerOptions(windowHandle)
    {
        UseDefaultBrokerAccount = true,
    });

// code omitted for brevity

LogsQueryClient client = new(credential);
Response<LogsQueryResult> response = await client.QueryResourceAsync(
    new ResourceIdentifier(resourceId), query, QueryTimeRange.All);

When the preceding code is run, notice the following excerpt from the logs:

False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:20:04Z - 42bcd4c1-0a29-441c-8f89-2e6a37f2d37e] === Token Acquisition (SilentRequest) started:
         Scopes: https://api.loganalytics.io//.default
        Authority Host: login.microsoftonline.com
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:20:04Z - 42bcd4c1-0a29-441c-8f89-2e6a37f2d37e] Broker is configured and enabled, attempting to use broker instead.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:20:04Z] WAM supported OS.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:20:04Z] [RuntimeBroker] WAM supported OS.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:20:05Z - 42bcd4c1-0a29-441c-8f89-2e6a37f2d37e] Can invoke broker. Will attempt to acquire token with broker.

False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:20:05Z] [MSAL:0002]     INFO    LogTelemetryData:340    Key: api_name, Value: SignInSilently

View console logs in WinForms app


To view these logs for the WinForms app, open the project’s Properties dialog in Visual Studio. Change the Output type setting from Windows Application to Console Application.

WinForms Output type drop-down list in project properties

Because the Azure Identity library delegates to the underlying MSAL dependency for its WAM support, MSAL log entries are produced. Notice the (SilentRequest) text, indicating that the account picker dialog will be suppressed.

If the UseDefaultBrokerAccount property is omitted or set to false, a subsequent run reveals the following log entries. Notice the (InteractiveRequest) text, indicating that an account picker dialog is necessary to support authentication.

False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:04:29Z - 65f48b47-0895-411f-b44b-f5c3d15ec30c] === Token Acquisition (InteractiveRequest) started:
         Scopes: https://api.loganalytics.io//.default
        Authority Host: login.microsoftonline.com
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:04:30Z - 65f48b47-0895-411f-b44b-f5c3d15ec30c] Broker is configured. Starting broker flow without knowing the broker installation app link.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:04:30Z] WAM supported OS.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:04:30Z] [RuntimeBroker] WAM supported OS.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:04:30Z - 65f48b47-0895-411f-b44b-f5c3d15ec30c] Can invoke broker. Will attempt to acquire token with broker.
False MSAL 4.56.0.0 MSAL.NetCore .NET 8.0.2 Microsoft Windows 10.0.22631 [2024-04-04 00:04:30Z] [RuntimeBroker] Calling SignInInteractivelyAsync this will show the account picker.

Finally, here’s a video demonstrating the interactive and silent authentication experiences:

Feedback

We value your feedback on this new feature. How can we improve upon the existing authentication broker support in the Azure Identity client libraries? Let’s have those conversations on GitHub at these locations:

Ecosystem-specific source code can be found on GitHub at the following locations:

2 comments

Leave a comment

  • Michael Taylor 0

    This seems like an app choice rather than a user choice. How would a user elect to pick the “default” account they want to use or at least let the app determine that the user may have multiple accounts and therefore shouldn’t use the default?

    Here’s the problem I have. I am logged into WIndows using my personal MS account. Always have been. However since I do company work on this computer I also have a work account. For reasons that I don’t understand Windows ALWAYS defaults to wanting to use my work account even though on my Edge browser I have never used my work account. I always use my personal account. So every time I have to authenticate (such as for leaving a comment here) I get the list of accounts but only my work account shows up. I have to click the Back button to get back to the list where I see both my personal (logged in) and work accounts so I can select my personal account. I have to do this every time on my machine.

    If an app “opts in” to using this silent approach wouldn’t it always use my work account even though I never want it to? How would an app be able to determine that potentially multiple accounts could be used and therefore either shouldn’t use silent mode or “allow” the user to set the “default” account to use?

    • Scott AddieMicrosoft employee 0

      Thanks for reading, Michael! You’re correct that this is an app choice. The app needs to expose a setting that allows a user to toggle the mode in which authentication occurs.

      Currently, the Azure Identity libraries don’t expose an API to determine whether multiple connected MSA and Entra accounts exist. If that’s something you’d like to see, I encourage you to open a GitHub issue using the language-specific link in the Feedback section of this blog post.

Feedback usabilla icon