{"id":2921,"date":"2023-12-07T09:00:24","date_gmt":"2023-12-07T17:00:24","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=2921"},"modified":"2023-12-07T10:02:38","modified_gmt":"2023-12-07T18:02:38","slug":"wham-authentication-broker-support-lands-in-the-azure-identity-libraries","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wham-authentication-broker-support-lands-in-the-azure-identity-libraries\/","title":{"rendered":"Wham! Authentication broker support lands in the Azure Identity libraries."},"content":{"rendered":"<p>In the November release of the Azure Identity client libraries, system authentication broker support reached stable form. Extension packages were created to enable this interactive authentication feature, as displayed in the following table.<\/p>\n<table>\n<thead>\n<tr>\n<th>Ecosystem<\/th>\n<th>Package<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>.NET<\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Azure.Identity.Broker\">Azure.Identity.Broker<\/a><\/td>\n<\/tr>\n<tr>\n<td>Java<\/td>\n<td><a href=\"https:\/\/central.sonatype.com\/artifact\/com.azure\/azure-identity-broker\">azure-identity-broker<\/a><\/td>\n<\/tr>\n<tr>\n<td>JavaScript<\/td>\n<td><a href=\"https:\/\/www.npmjs.com\/package\/@azure\/identity-broker\">@azure\/identity-broker<\/a><\/td>\n<\/tr>\n<tr>\n<td>Python<\/td>\n<td><a href=\"https:\/\/pypi.org\/project\/azure-identity-broker\/\">azure-identity-broker<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For now, this feature is limited to Windows users only. At the time of writing, the team is designing macOS broker support; Linux support follows that release.<\/p>\n<h2>What is a system authentication broker?<\/h2>\n<p>A <em>system authentication broker<\/em> is an app running on a user&#8217;s machine that manages the authentication handshakes and token maintenance for all connected accounts. On Windows, the authentication broker is <em>Web Account Manager (WAM)<\/em>. WAM made its debut in Windows 10 and Windows Server 2019 and continues to ship in the latest releases of Windows. Open the <strong>Services<\/strong> snap-in control file via <code>services.msc<\/code>, and you see WAM listed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-wam-service.png\" alt=\"WAM in the Windows Services window\" \/><\/p>\n<p>WAM is a broker service that allows apps to request OAuth tokens from identity providers, such as Microsoft Entra ID, in a seamless fashion. With it, identity providers can natively plug into the OS and provide the service to other apps. In no particular order, WAM offers the following benefits:<\/p>\n<ul>\n<li><strong>Feature support.<\/strong> Apps can access OS-level and service-level capabilities, including Windows Hello, conditional access policies, and FIDO keys.<\/li>\n<li><strong>Streamlined single sign-on.<\/strong> Apps use the built-in account picker, allowing the user to select an existing account instead of repeatedly entering the same credentials.<\/li>\n<li><strong>Enhanced security.<\/strong> Bug fixes and enhancements ship with Windows.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/entra\/identity\/conditional-access\/concept-token-protection\"><strong>Token protection.<\/strong><\/a> Refresh tokens are device-bound, and apps can acquire device-bound access tokens.<\/li>\n<\/ul>\n<p>Many of Microsoft&#8217;s developer tools, including <a href=\"https:\/\/learn.microsoft.com\/visualstudio\/ide\/work-with-multi-factor-authentication?view=vs-2022#enabling-windows-authentication-broker\">Visual Studio<\/a>, <a href=\"https:\/\/learn.microsoft.com\/cli\/azure\/authenticate-azure-cli-web-account-manager\">Azure CLI<\/a>, and <a href=\"https:\/\/learn.microsoft.com\/powershell\/azure\/authenticate-interactive?view=azps-11.0.0#web-account-manager-wam\">Azure PowerShell<\/a>, already provide WAM integration.<\/p>\n<h2>Interactive, brokered authentication in the Azure Identity libraries<\/h2>\n<p>The Azure Identity libraries&#8217; <code>InteractiveBrowserCredential<\/code> type was extended to support WAM. Personal Microsoft accounts and work or school accounts are supported. If a supported version of Windows is used, the <a href=\"https:\/\/learn.microsoft.com\/entra\/msal\/dotnet\/acquiring-tokens\/using-web-browsers#browser-availability\">default browser<\/a>-based UI is replaced with a smoother authentication experience, similar to Windows built-in apps.<\/p>\n<p>What does the aforementioned default browser-based UI look like? On Windows, there are a couple possibilities:<\/p>\n<ol>\n<li><strong>Embedded view<\/strong>: A web browser hosted in a UI control. For example, a <a href=\"https:\/\/learn.microsoft.com\/microsoft-edge\/webview2\/get-started\/winforms\">Microsoft Edge WebView2 control used in a WinForms app<\/a>.<br\/><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-embedded-view.png\" alt=\"Embedded view account selector window\" width=\"330\" height=\"400\" \/><\/li>\n<li><strong>System browser<\/strong>: The web browser designated as the system&#8217;s default choice\u2014Microsoft Edge in the following screenshot.<br\/>\n \t<img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-system-browser.png\" alt=\"System browser account selector window\" width=\"373\" height=\"400\" \/><\/li>\n<\/ol>\n<p>On macOS, Linux, and earlier versions of Windows\u2014systems on which WAM isn&#8217;t supported\u2014the Azure Identity libraries default to a browser-based authentication experience.<\/p>\n<h3>Get started<\/h3>\n<p>To use WAM in your app, complete these steps:<\/p>\n<ol>\n<li>Add the following WAM redirect URI within your <a href=\"https:\/\/learn.microsoft.com\/entra\/identity-platform\/quickstart-register-app\">Microsoft Entra app registration<\/a> in the Azure portal:\n<pre><code>ms-appx-web:\/\/microsoft.aad.brokerplugin\/{client_id}<\/code><\/pre>\n<p>The <code>{client_id}<\/code> placeholder must be replaced with the <strong>Application (client) ID<\/strong> listed on the <strong>Overview<\/strong> blade of the app registration.<\/li>\n<li>Install the Azure Identity and Azure Identity Broker packages.\n<ul>\n<li><strong>.NET<\/strong>:\n<pre><code>dotnet add package Azure.Identity\r\ndotnet add package Azure.Identity.Broker<\/code><\/pre>\n<\/li>\n<li><strong>Java<\/strong>: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/main\/sdk\/identity\/azure-identity-broker#include-the-bom-file\">Include the BOM file<\/a> or <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/main\/sdk\/identity\/azure-identity-broker#include-direct-dependency\">Include the direct dependency<\/a><\/li>\n<li><strong>JavaScript<\/strong>:\n<pre><code>npm install --save @azure\/identity @azure\/identity-broker<\/code><\/pre>\n<\/li>\n<li><strong>Python<\/strong>:\n<pre><code>pip install azure-identity azure-identity-broker<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>Create a broker-enabled instance of <code>InteractiveBrowserCredential<\/code> in your app. The credential requires the handle of the parent window that&#8217;s requesting the authentication flow. On Windows, the handle is an integer value that uniquely identifies the window.\n<ul>\n<li><strong>.NET<\/strong>:\n<pre><code class=\"language-csharp\">using Azure.Identity;\r\nusing Azure.Identity.Broker;\r\n\r\n\/\/ code omitted for brevity\r\n\r\nIntPtr windowHandle = GetForegroundWindow();\r\nInteractiveBrowserCredential credential = new(\r\n    new InteractiveBrowserCredentialBrokerOptions(windowHandle)\r\n);<\/code><\/pre>\n<\/li>\n<li><strong>Java<\/strong>:\n<pre><code class=\"language-java\">import com.azure.identity.InteractiveBrowserCredential;\r\nimport com.azure.identity.broker.InteractiveBrowserBrokerCredentialBuilder;\r\n\r\n\/\/ code omitted for brevity\r\n\r\nlong windowHandle = getWindowHandle();\r\nInteractiveBrowserCredential credential = \r\n    new InteractiveBrowserBrokerCredentialBuilder()\r\n        .setWindowHandle(windowHandle)\r\n        .build();<\/code><\/pre>\n<\/li>\n<li><strong>JavaScript<\/strong>:\n<pre><code class=\"language-javascript\">import { nativeBrokerPlugin } from \"@azure\/identity-broker\";\r\nimport { \r\n  useIdentityPlugin,\r\n  InteractiveBrowserCredential,\r\n} from \"@azure\/identity\";\r\n\r\nuseIdentityPlugin(nativeBrokerPlugin);\r\n\r\n\/\/ code omitted for brevity\r\n\r\nlet windowHandle = getWindowHandle();\r\n\r\nconst credential = new InteractiveBrowserCredential({\r\n  brokerOptions: {\r\n    enabled: true,\r\n    parentWindowHandle: windowHandle,\r\n  },\r\n});<\/code><\/pre>\n<\/li>\n<li><strong>Python<\/strong>:\n<pre><code class=\"language-python\">import win32gui\r\nfrom azure.identity.broker import InteractiveBrowserBrokerCredential\r\n\r\n# code omitted for brevity\r\n\r\nwindow_handle = win32gui.GetForegroundWindow()\r\n\r\ncredential = InteractiveBrowserBrokerCredential(\r\n    parent_window_handle=window_handle\r\n)<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>Use the broker-enabled <code>InteractiveBrowserCredential<\/code> instance.<\/li>\n<\/ol>\n<h3>A .NET developer&#8217;s end-to-end experience<\/h3>\n<p>As a .NET developer, imagine a scenario in which you created a desktop app using WinForms and C#. In that app, you use an Azure Monitor Query client library to query a Log Analytics workspace. The <code>LogsQueryClient<\/code> object in the Monitor Query library requires authentication of a work or school account to Microsoft Entra ID. You&#8217;d complete the following steps to use and test WAM:<\/p>\n<ol>\n<li>Install the following NuGet packages:\n<pre><code class=\"language-xml\">&lt;ItemGroup&gt;\r\n  &lt;PackageReference Include=\"Azure.Identity\" Version=\"1.10.4\" \/&gt;\r\n  &lt;PackageReference Include=\"Azure.Identity.Broker\" Version=\"1.0.0\" \/&gt;\r\n  &lt;PackageReference Include=\"Azure.Monitor.Query\" Version=\"1.2.0\" \/&gt;\r\n&lt;\/ItemGroup&gt;<\/code><\/pre>\n<\/li>\n<li>Get the handle of the parent window to which the WAM account picker window should be docked:\n<pre><code class=\"language-csharp\">private async void testBrokeredAuth_Click(object sender, EventArgs e)\r\n{\r\n    IntPtr windowHandle = this.Handle;\r\n\r\n    \/\/ code omitted for brevity\r\n}<\/code><\/pre>\n<blockquote><p>NOTE: To obtain a window handle for other .NET app models, such as WPF and console apps, see <a href=\"https:\/\/learn.microsoft.com\/entra\/msal\/dotnet\/acquiring-tokens\/desktop-mobile\/wam#parent-window-handles\">Parent window handles<\/a>.<\/p><\/blockquote>\n<\/li>\n<li>Create an instance of <code>InteractiveBrowserCredential<\/code> that accepts <code>InteractiveBrowserCredentialBrokerOptions<\/code>, passing in a window handle pointer:\n<pre><code class=\"language-csharp\">using Azure.Identity;\r\nusing Azure.Identity.Broker;\r\n\r\n\/\/ code omitted for brevity\r\n\r\nInteractiveBrowserCredential credential;\r\n\r\nif (windowHandle != IntPtr.Zero)\r\n{\r\n    credential = new(\r\n        new InteractiveBrowserCredentialBrokerOptions(windowHandle)\r\n    );\r\n}<\/code><\/pre>\n<\/li>\n<li>Pass the <code>InteractiveBrowserCredential<\/code> instance to the Azure SDK library&#8217;s client. In this example, the Azure Monitor Query library&#8217;s <code>LogsQueryClient<\/code> is used:\n<pre><code class=\"language-csharp\">\/\/ code omitted for brevity\r\n\r\nLogsQueryClient client = new(credential);\r\n\r\nResponse&lt;LogsQueryResult&gt; response = await client.QueryResourceAsync(\r\n    new ResourceIdentifier(resourceId), query, QueryTimeRange.All);<\/code><\/pre>\n<p>When this final line of code executes, an account picker window appears:<\/p>\n<p><div style=\"width: 640px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-2921-1\" width=\"640\" height=\"360\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-wam.mp4?_=1\" \/><a href=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-wam.mp4\">https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-wam.mp4<\/a><\/video><\/div><\/p>\n<p>Behind the scenes, the Microsoft Entra token broker plugin, represented by the <code>Microsoft.AAD.BrokerPlugin.exe<\/code> background process, facilitates authentication on behalf of the WinForms app.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2023\/12\/2023-11-30-\" alt=\"Task Manager view of the Microsoft Entra token broker plugin process\" \/><\/li>\n<\/ol>\n<h2>Feedback<\/h2>\n<p>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&#8217;s have those conversations on GitHub at these locations:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/issues\">.NET<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/issues\">Java<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/issues\">JavaScript<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/issues\">Python<\/a><\/li>\n<\/ul>\n<p>Ecosystem-specific source code can be found on GitHub at the following locations:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/main\/sdk\/identity\/Azure.Identity.Broker\">.NET<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/main\/sdk\/identity\/azure-identity-broker\">Java<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/main\/sdk\/identity\/identity-broker\">JavaScript<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/tree\/main\/sdk\/identity\/azure-identity-broker\">Python<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to use a system authentication broker via the Azure Identity client libraries.<\/p>\n","protected":false},"author":63456,"featured_media":2938,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[701,927,841,750,160,159,162,24],"class_list":["post-2921","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-net","tag-authentication","tag-azure-identity","tag-azure-sdk","tag-java","tag-javascript","tag-python","tag-releases"],"acf":[],"blog_post_summary":"<p>Learn how to use a system authentication broker via the Azure Identity client libraries.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/2921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/users\/63456"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=2921"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/2921\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/2938"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=2921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=2921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=2921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}