Skip to content

Using Web Account Manager with MSAL Java

Avery-Dunn edited this page Jun 23, 2023 · 3 revisions

Note: This functionality is currently in a beta release of both the MSAL Java package (1.14.x-beta) and the MSAL Java Brokers package (1.0.x-beta) while they undergo internal testing. Although the core functionality and APIs are most likely finalized, anything described here could potentially change during the beta. This page will be kept up to date with the latest beta version, as well as the final release.


Web Account Manager (WAM) is a Windows 10+ component that can act as an authentication broker, allowing your users to easily authenticate with external identity providers as well as Microsoft. To avoid the hassle of trying to access a native API from a Java application, MSAL Java offers a simple API to easily get your app to start using WAM.

Before you start

In addition to the main msal4j package you may be familiar with, your project will need a new dependency: msal4j-brokers. This package contains everything that is needed for MSAL Java to access the native WAM API on your behalf.

How to enable brokers in your application

Once you have msal4j and msal4j-brokers as dependencies in your project, you will be able to find two important classes and one important parameter:

  • IBroker in msal4j, which is an interface acquireToken APIs similar to the ones already in MSAL Java
  • MsalRuntimeBroker in msal4j-brokers, which implements IBroker and provides access to the underlying code that's interacting with WAM
  • The broker parameter in msal4j's PublicClientApplication builder, which will allow you to tell MSAL Java which IBroker implementation to use

To start using WAM in your application, you simply need to pass an instance of MsalRuntimeBroker into PublicClientApplication's broker parameter:

MsalRuntimeBroker broker = new MsalRuntimeBroker();

PublicClientApplication pca = PublicClientApplication.builder(clientId).
    authority(authority).
    broker(broker).
    build();

And that's it. Once a broker is set, whenever you call one of MSAL Java's existing acquireToken APIs it will attempt to use the broker you provided, in this case the one for WAM.

Currently the only supported broker is WAM, and the support for it comes from a project called MSALRuntime, which is a project related to MSAL C++.

Supported Flows, Features, and Limitations

Not all platforms support WAM, so if your application is running on an OS where WAM is not supported then MSAL Java will log a warning saying so and fall back to traditional authentication flows.

Currently, MSAL Java provides supported for using WAM in: Windows 10+ 32-bit, 64-bit, and ARM64

Additionally, only certain scenarios are supported by WAM. Currently only public client scenarios are supported, and only for these auth flows:

Auth flow Notes
Silent Supports both the existing MSAL Java behavior of retrieving cached tokens (if an account is provided to SilentParameters), as well new behavior of attempting a silent sign-in using the default OS account (if no account is provided)
Interactive Rather than opening a browser tab, WAM currently pops up a UI window where your users can enter their credentials, and in order to properly show that window to your users you should provide the window handle of your application as part of the request. If your application is console-based we should be able to discover the window handle for you, however if your application contains multiple custom UI elements then you should provide the window handle to avoid issues (such as the popup appearing behind other windows, blocking unrelated UI elements, etc.)
Username/Password This flow may become deprecated in MSAL Java in the near future, and is already marked as deprecated in msal4j-brokers. However, the behavior is the same as basic MSAL Java: simply provide a username and password, and WAM will attempt to use those credentials to get a token

New to MSAL Java is the concept of proof-of-possession(POP) tokens, which are tokens that are bound to a specific device and resource. In order to get POP tokens you must have enabled the broker in your client app, and from then on you need only use the new proofOfPossession() option in the parameters builder for one of the above flows. For example, here is how to get a POP token in the interactive flow:

InteractiveRequestParameters parameters = InteractiveRequestParameters.builder(someUrl)
                .scopes(someScopes);
                .proofOfPossession(httpMethod, resourceUri, nonce)
                .build()

IAuthenticationResult result = someClientApp.acquireToken(parameters);

The proofOfPossession parameter takes three items:

Parameter Notes
HTTP Method An HTTP method (GET, POST, etc.) that will be used to access the resource URI
Resource URI The URI of the resource the token should be bound to
Nonce In most cases, this can be null. Certain scenarios will return a claims challenge containing a nonce as part of a token request rather than a token. If this happens, simply copy the nonce value from the claims challenge and retry the token request with the nonce in the parameter. (TODO: links to relevant docs for this advanced scenario)

Handling exceptions

Although the API in MSAL Java is simple, the underlying functionality is handled by several different Java and native packages, some of which we do not have direct control over. Exceptions and errors can come from any part of this chain, however MSAL Java tries to add context and information to errors whenever possible.

MSAL Java will provide useful error messages and error codes directly from MSALRuntime/WAM when relevant, however for deeper debugging you can enable logging directly from MSALRuntime via the MsalRuntimeBroker object:

MsalRuntimeBroker broker = new MsalRuntimeBroker();

MsalRuntimeInterop.enableLogging(enableLogging); //Allows MSAL Java to log all logs produced by MSALRuntime
MsalRuntimeInterop.enableLoggingPii(enablePII); //Allows PII data to appear in logs. If false, you will see '(pii)' or similar in logs where PII data would have appeared

This logging can be activated/deactivated at any point via the above APIs, and they will follow the same verbosity level as MSAL Java. Note: while they will follow the same logging level as MSAL Java (info/debug/error/etc.), at each level MSALRuntime tends to be much more verbose that MSAL Java, so this setting is likely only useful for debugging.

Extra details

Note: This section is not necessary for using WAM or msal4j-brokers, and is just meant to get extra clarity and background on all the components involved.

Although the API for enabling a broker is very simple, under the hood a number of packages are used to actually provide this feature:

  • msal4j-brokers - Essentially a thin layer between msal4j and javamsalruntime, meant to handle the conversion between requests from msal4j and results from javamsalruntime
  • javamsalruntime - A Java project that uses JNA to call into native code, converting Java classes and variables into C#/C++ equivalents and vice versa
  • MSALRruntime - A C++/C# project that provides APIs for accessing WAM and a number of other features, and eventually other auth brokers. This project produces the dll packages that javamsalruntime calls via JNA, and is the ultimate decider for what scenarios msal4j-brokers can support

In short, the full package setup looks something like this:

PackageDiagram drawio

Clone this wiki locally