Exchange Online Management PowerShell Connect-ExchangeOnline bug "A window handle must be configured. See https://aka.ms/msal-net-wam#parent-window-handles"

If you're using the Exchange Online Management PowerShell cmdlets you may notice that the following error:

A window handle must be configured. See https://aka.ms/msal-net-wam#parent-window-handles

This error appears in version 3.7.0 (and persists in version 3.7.1) when the following change was made.

Integrated WAM (Web Account Manager) in Authentication flows to enhance security.

You notice that this error occurs in PowerShell ISE but not in a PowerShell, the issue also appears in any Windows based applications - for example a WinForms application that tries to execute Connect-ExchangeOnline

PowerShell ISE


A .NET console application does work correctly.

.NET console application




While you're here why not check out our Exchange audit and documentation tool?


The error occurs because Microsoft has made the (correct) decision that when an interactive login prompt it must have a parent window so that the dialog doesn't appear behind another window thereby not visible to the user. This is implemented by the MSAL library.

However the code they used to determine the parent window can be seen below.

/// <summary>
/// Initializes the Public Client Application or extract from map
/// if already present. Also it enters the instance in the map if newly created.
/// </summary>
/// <returns>An instance of PCA from the map or intializes and returns it</returns>
private IPublicClientApplication GetPublicClientInstance()
{
    IPublicClientApplication publicClientApplication;
    if (!MSALTokenProvider.publicClientApplicationMap.TryGetValue(this.context.AzureADAuthorizationEndpointUri, out publicClientApplication))
    {
        BrokerOptions brokerOption = new BrokerOptions(BrokerOptions.OperatingSystems.Windows);
        publicClientApplication = (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? PublicClientApplicationBuilder.Create(this.context.ClientAppId).WithAuthority(this.context.AzureADAuthorizationEndpointUri, true).WithRedirectUri(this.context.ClientAppRedirectUri.ToString()).WithClientCapabilities(new string[] { "cp1" }).Build() : PublicClientApplicationBuilder.Create(this.context.ClientAppId).WithAuthority(this.context.AzureADAuthorizationEndpointUri, true).WithRedirectUri(this.context.ClientAppRedirectUri.ToString()).WithClientCapabilities(new string[] { "cp1" }).WithParentActivityOrWindow(new Func<IntPtr>(ParentWindowHandle.GetConsoleOrTerminalWindow)).WithBroker(brokerOption).Build());MSALTokenProvider.publicClientApplicationMap.TryAdd(this.context.AzureADAuthorizationEndpointUri, publicClientApplication);
    }
    return publicClientApplication;
}

As seen in the code above this uses the GetConsoleWindow low level API to determine the handle of the parent console window.
https://learn.microsoft.com/windows/console/getconsolewindow


"We do not recommend using this content in new products"

They are using dated methods that they don't recommend themselves, but more importantly they are looking for a console window and therefore if you're not running a console app then there's no handle returned from the method.


The issue persists in ExchangeOnlineManagement version 3.7.1 so it's a concern that Microsoft are not going to fix this issue.





Comments

Popular posts from this blog

Windows Server 2016, 2019, 2022, Windows 10 and Windows 11: Date and time "Some settings are managed by your organization".

TFTPD32 or TFTPD64 reports Bind error 10013 An attempt was made to access a socket in a way forbidden by its access permissions.

When using the "Send to compressed (zipped) folder" context menu item nothing happens