Improved Windows Broker Support with MSAL.NET

Sameer Khandekar

Den Delimarsky

The Identity SDK team just released a brand-new version of the Microsoft Authentication Library (MSAL) for .NET that introduces an improved experience for developers using authentication brokers to simplify how they acquire and use tokens in their applications.

To take advantage of the new broker functionality, developers will need to use the Microsoft.Identity.Client package from NuGet, starting with version 4.52.0.

What is a Broker

An authentication broker is an application that runs on a user’s machine that handles the authentication handshakes and token maintenance for connected accounts. As its authentication broker, the Windows operating system uses the Web Account Manager (WAM), which is supported on Windows Server 2019 and above, Windows 10, and Windows 11. It has many benefits for developers and customers alike, including:

  • Enhanced security. The client application does not need to manage the refresh token which can be used to obtain new authentication tokens without the user consent.
  • Feature support. With the help of the broker developers can access rich OS and service capabilities such as Windows Hello, Conditional Access Policies, and FIDO keys without writing extra scaffolding code.
  • System integration. Applications that use the broker plug-and-play with the built-in account picker, allowing the user to quickly pick an existing account instead of reentering the same credentials over and over.

With the help of a broker you need to write less code to handle token-related logic while also being able to use more advanced functionality, such as Proof-of-Possession tokens. Moving forward, our team is continuing to invest in making sure that brokers are the de-facto approach to authenticate with MSAL-based applications, where possible.

What is Changing

Recently, an updated authentication broker experience was made available for Windows systems. The new broker is written in C++, is well tested, and is significantly more performant and secure. One of the biggest consumers of the new broker experience is the Microsoft 365 suite of apps.

With the introduction of the updated broker, we’ve also updated MSAL.NET to expose its capabilities under a simplified API. The improved broker experience in MSAL.NET will replace the existing broker flows by default – developers do not need to take any extra steps. An exception to this are Universal Windows Platform (UWP) applications – they will continue to use the legacy authentication broker due to Windows API limitations.

Using the New Broker

To use the new broker, developers will need to use the RuntimeBroker class, hosted in Microsoft.Identity.Client package. Most of the frameworks supported by MSAL.NET will need that package only, with a few exceptions. See the table below for a detailed mapping.

Framework Microsoft.Identity.Client Microsoft.Identity.Client.Broker Microsoft.Identity.Client.Desktop
net48 ✅ (not recommended)
net6.0
net6.0-windows
UWP
.NET MAUI
netcoreapp3.1 (not recommended) ✅ (not recommended)

Because the netcoreapp3.1 target framework has reached the end of life this past December, our team will no longer offer support for applications using MSAL with the specific version of .NET Core. We recommend upgrading to the latest version where possible.

Parent Window Requirement

Specifying a parent window handle was an optional parameter when working with the legacy broker. When a parent window handle was not provided, the window for entering user credentials could pop up anywhere, making for a less than ideal experience, as the window could be obstructed by another window or displayed on a screen where the user does not expect to see it.

To mitigate the issue, starting with the latest version of MSAL.NET, specifying the parent window handle is now required when working with the Windows authentication broker. Developers will be able to specify the window they want to bind the broker popup to via WithParentActivityOrWindow.

Because the new broker is not available through the UWP API surface, the function cannot be used inside a UWP application.

Examples

To get a better understanding of how to use the new broker, let’s take a look at a few examples across the matrix of supported frameworks.

.NET Framework

Start by including the Microsoft.Identity.Client and Microsoft.Identity.Client.Broker packages. You could then use code like the snippet below to access the broker:

var pcaBuilder = PublicClientApplicationBuilder
                .Create(s_clientIdForPublicApp)
                .WithAuthority(Authority)
                .WithLogging(Log, LogLevel.Verbose, true)
                .WithRedirectUri("http://localhost") // required for DefaultOsBrowser
                .WithParentActivityOrWindow(consoleWindowHandleProvider);

BrokerOptions options = new BrokerOptions(BrokerOptions options = new BrokerOptions(BrokerOptions.OperatingSystems.Windows));

// Set the desired properties such as Title, ListOperatingSystemAccounts
options.<desired property> = ...;

pcaBuilder.WithWindowsDesktopFeatures(options);

var pca = PublicClientApplicationBuilder.Create(...)
                    .WithWindowsDesktopFeatures(options)
                    .WithParentActivityOrWindow(consoleWindowHandleProvider)
                    .Build();

AuthenticationResult result = pca.AcquireTokenInteractive(Scopes)
                                 .ExecuteAsync()
                                 .ConfigureAwait(false);
.NET 6.0

Make sure to include the Microsoft.Identity.Client and Microsoft.Identity.Client.Broker packages in your project. You can then use the broker as follows:

var pcaBuilder = PublicClientApplicationBuilder
                .Create(s_clientIdForPublicApp)
                .WithAuthority(Authority)
                .WithLogging(Log, LogLevel.Verbose, true)
                .WithRedirectUri("http://localhost") // required for DefaultOsBrowser
                .WithParentActivityOrWindow(consoleWindowHandleProvider);

BrokerOptions options = new BrokerOptions(BrokerOptions options = new BrokerOptions(BrokerOptions.OperatingSystems.Windows));

// Set the desired properties such as Title, ListOperatingSystemAccounts
options.<desired property> = ...;

pcaBuilder.WithBroker(options); // this is the only line different from .net6.0

var pca = PublicClientApplicationBuilder.Create(...)
                    .WithWindowsDesktopFeatures(options)
                    .WithParentActivityOrWindow(consoleWindowHandleProvider)
                    .Build();

AuthenticationResult result = pca.AcquireTokenInteractive(Scopes)
                                 .ExecuteAsync()
                                 .ConfigureAwait(false);
.NET 6.0 (Windows-specific)

If you are building a net6.0-windows application, you only need to include the Microsoft.Identity.Client package. The rest of the broker-related code is exactly the same as in the .NET 6.0 snippet above.

Universal Windows Platform

No changes are required for UWP applications. Because the platform does not support the updated broker, existing applications should continue using WebAuthenticationBroker.

MAUI and Xamarin

For both MAUI and Xamarin, developers will need to use the RuntimeBroker class. When calling AcquireTokenInteractive, a parent window handle will now be required.

return await PCA.AcquireTokenInteractive(scopes)
       .WithParentActivityOrWindow(PlatformConfig.Instance.ParentWindow)
       .ExecuteAsync()
       .ConfigureAwait(false);

Upgrading From Preview Releases

If you have previously used a preview release of MSAL, keep in mind that the WithBrokerPreview API is now deprecated. The stable API is now exposed through WithBroker(BrokerOptions) and you should update your code accordingly.

Upgrading Older Applications

The biggest change around the new broker for existing applications is related to the WithWindowsBroker API call – it will now require a parent window handle. When invoked, it will automatically rely on the new broker experience. There are many ways to obtain a window handle depending on the application. We recommend checking out the Retrieve a window handle (HWND) for more details.

Additionally, we’ve added WithWindowsDesktopFeatures to support legacy applications and marked WithDesktopFeatures API as obsolete.

Addressing Multiple Frameworks

If you have multiple target frameworks in your project, relevant MSAL packages can be imported as follows:

  <ItemGroup>
    <PackageReference Include="Microsoft.Identity.Client" Version="4.52.0" />
  </ItemGroup>

 <ItemGroup Condition="'$(TargetFramework)' == 'net48'">
    <PackageReference Include="Microsoft.Identity.Client.Desktop" Version="4.52.0" />
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>

  <ItemGroup Condition="$(TargetFramework) == 'net6.0' ">
    <PackageReference Include="Microsoft.Identity.Client.Broker" Version="4.52.0" />
  </ItemGroup>

Reference Project

If you’re ready to dive in, a reference project for the new broker can be found in the library source code repository on GitHub. This sample shows how to get started along with the many different variations in ways in which the Windows broker can be used to authenticate a user.

Feedback

We would like to extend a huge thank you to our partners and community for helping shape the new broker API. As the library evolves, we would love to hear more from you on how we can improve the developer experience and our feature set – open a new issue for any feedback and we will address it as soon as possible.