{"id":109394,"date":"2024-02-12T07:00:00","date_gmt":"2024-02-12T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109394"},"modified":"2024-02-12T06:14:02","modified_gmt":"2024-02-12T14:14:02","slug":"20240212-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240212-00\/?p=109394","title":{"rendered":"How can I get the Windows Runtime HttpClient to display a basic authentication prompt?"},"content":{"rendered":"<p>A customer was trying to get the Windows Runtime <code>Windows.<wbr \/>Web.<wbr \/>Http.<wbr \/>HttpClient<\/code> to display a basic authentication prompt when used from a classic Win32 application. Unfortunately, no authentication dialog appeared even though they set <code>AllowUI = true<\/code>; the request reported status 401 (Unauthorized).<\/p>\n<pre>namespace winrt\r\n{\r\n    using namespace winrt::Windows::Foundation;\r\n    using namespace winrt::Windows::Web::Http;\r\n    using namespace winrt::Windows::Web::Http::Filters;\r\n}\r\n\r\nwinrt::IAsyncOperation&lt;winrt::HttpStatusCode&gt; Sample(HWND hwnd)\r\n{\r\n    auto uri = winrt::Uri(L\"http:\/\/httpbin.org\/basic-auth\/user\/password\");\r\n    auto filter = winrt::HttpBaseProtocolFilter();\r\n    filter.AllowUI(true);\r\n\r\n    auto client = winrt::HttpClient(filter);\r\n    auto result = co_await client.GetAsync(uri);\r\n\r\n    co_return result.StatusCode();\r\n}\r\n<\/pre>\n<p>Originally, the objects in the Windows Runtime namespace were intended for use in UWP apps (Universal Windows Platform). In UWP apps, each thread can have at most one CoreWindow object, and it was common for Windows Runtime objects to infer their UI context by asking the thread for its CoreWindow, and then using that CoreWindow for any further user interface operations.\u00b9<\/p>\n<p>But classic Win32 apps don&#8217;t follow the &#8220;one CoreWindow per thread&#8221; model. They can create multiple windows on each thread, and none of them are required to be a CoreWindow. Under these conditions, Windows Runtime objects that were designed for UWP apps run into a problem: What window should they use for user interface operations?<\/p>\n<p>When used in a classic Win32 app, the <code>Http\u00adBase\u00adProtocol\u00adFilter<\/code> tries to guess which window to use: Sometimes it guesses correctly, sometimes it guesses wrong, and sometimes its guess comes up empty.<\/p>\n<p>To avoid guessing, use the <code>IInitialize\u00adWith\u00adWindow<\/code> interface (which <a title=\"How can a desktop app use a Windows Runtime object that infers UI context from its thread? The IInitializeWithWindow pattern\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190412-00\/?p=102413\"> we learned about earlier<\/a>) to give the <code>Http\u00adBase\u00adProtocol\u00adFilter<\/code> an explicit window to use.<\/p>\n<pre>namespace winrt\r\n{\r\n    using namespace winrt::Windows::Foundation;\r\n    using namespace winrt::Windows::Web::Http;\r\n    using namespace winrt::Windows::Web::Http::Filters;\r\n}\r\n\r\nwinrt::IAsyncOperation&lt;winrt::HttpStatusCode&gt; Sample(HWND hwnd)\r\n{\r\n    auto uri = winrt::Uri(L\"http:\/\/httpbin.org\/basic-auth\/user\/password\");\r\n    auto filter = winrt::HttpBaseProtocolFilter();\r\n    <span style=\"border: solid 1px currentcolor;\">filter.as&lt;IInitializeWithWindow&gt;()-&gt;Initialize(hwnd);<\/span>\r\n    filter.AllowUI(true);\r\n\r\n    auto client = winrt::HttpClient(filter);\r\n    auto result = co_await client.GetAsync(uri);\r\n\r\n    co_return result.StatusCode();\r\n}\r\n<\/pre>\n<p>With this extra nudge, the <code>Http\u00adBase\u00adProtocol\u00adFilter<\/code> will be able to display the basic authentication dialog.<\/p>\n<p>\u00b9 This model stopped working even for UWP apps with the introduction of AppWindow objects, which let you create multiple windows on a single thread.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You need to give it some help finding the right window.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-109394","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You need to give it some help finding the right window.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=109394"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109394\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=109394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109394"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}