HOW TO: Use the Auth0 oidcClient.WinForms SDK with Edge Chromium / WebView2

The Problem
If you have a requirement to run your WinForms application as an Administrator you’ll discover that our SDK uses Microsoft Internet Explorer when you run your compiled executable as admin.

This may or may not work for you, and IE is ancient and barely supported in this day and age.

This is a known limitation with the WebView components provided by Microsoft.

On this page, you will find the following Note that indicates this behavior: WebViewCompatible control for Windows Forms and WPF - Windows Community Toolkit | Microsoft Learn

The Edge runtime does not at the moment work when the process is elevated as an administrator. Therefore WebViewCompatible will fall back to use the System.Windows.Controls.WebBrowser when it detects that the process is running as administrator.

A Workaround that eliminates IE from the equation:

By adding a class to your project that wraps Webview2 in an IBrowser interface you can use Edge Chromium with the Auth0 .net SDK in your desktop applications.

!!! This requires the WebView 2 components, you can download them here:
https://developer.microsoft.com/en-us/microsoft-edge/webview2/

Tested with the Auth0 Winforms Quickstart:
https://auth0.com/docs/quickstart/native/wpf-winforms/01-login

Implementation:

  1. Add the Webview2 Nuget package: Install-Package Microsoft.Web.WebView2

  2. Add the following class to your project webBrowserChromium.cs (you can name it whatever you like)

    using IdentityModel.OidcClient.Browser;
    using Microsoft.Toolkit.Forms.UI.Controls;
    using Microsoft.Web.WebView2.WinForms;
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsSample
    {
       
     /// <summary>
     /// Implements the <see cref="IBrowser"/> interface using the <see cref="WebView2"/> control.
     /// </summary>
     public class WebViewBrowserChromium : IBrowser
     {
         private readonly Func<Form> _formFactory;
    
         /// <summary>
         /// Creates a new instance of <see cref="WebViewBrowserChromium"/> with a specified function to create the <see cref="Form"/>
         /// used to host the <see cref="WebView2"/> control.
         /// </summary>
         /// <param name="formFactory">The function used to create the <see cref="Form"/> that will host the <see cref="WebViewCompatible"/> control.</param>
         public WebViewBrowserChromium(Func<Form> formFactory)
         {
             _formFactory = formFactory;
         }
    
         /// <summary>
         /// Creates a new instance of <see cref="WebViewBrowserChromium"/> allowing parts of the <see cref="Form"/> container to be set.
         /// </summary>
         /// <param name="title">Optional title for the form - defaults to 'Authenticating...'.</param>
         /// <param name="width">Optional width for the form in pixels. Defaults to 1024.</param>
         /// <param name="height">Optional height for the form in pixels. Defaults to 768.</param>
         public WebViewBrowserChromium(string title = "Authenticating...", int width = 1024, int height = 768)
             : this(() => new Form
             {
                 Name = "WebAuthentication",
                 Text = title,
                 Width = width,
                 Height = height
             })
         {
         }
    
         /// <inheritdoc />
         public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default)
         {
             var tcs = new TaskCompletionSource<BrowserResult>();
    
             var window = _formFactory();
             var webView = new WebView2 { Dock = DockStyle.Fill };
             await webView.EnsureCoreWebView2Async();
    
             webView.NavigationStarting += (sender, e) =>
             {
                 if (e.Uri.StartsWith(options.EndUrl))
                 {
                     
                     tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.Success, Response = e.Uri.ToString() });
                     window.Close();
                     
                 }
                     
             };
    
             window.Closing += (sender, e) =>
             {
                 if (!tcs.Task.IsCompleted)
                     tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.UserCancel });
             };
    
    
             window.Controls.Add(webView);
             window.Show();
             webView.CoreWebView2.Navigate(options.StartUrl);
             
    
             return await tcs.Task;
         }
     }
    }
    

Usage

You now have 3 browser choices with the Auth0 SDK:

  • Internet Explorer (the one we all know and loathe)
  • MS Edge (as implemented in the current WebView)
  • MS Edge Chromium (requires the WebView2 Runtime is present)

you can change browsers when you initialize the SDK by setting the Browser property

client = new Auth0Client(new Auth0ClientOptions
{
    Domain = domain,
    ClientId = clientId,
    EnableTelemetry = true,
            
    //Browser = new WebBrowserBrowser()         // Use IE (IBrowser contained within Auth0 SDK)
    //Browser = new WebViewBrowser()              // Use Edge (DEFAULT Auth0 setting - Will revert to IE if run as admin)
    
    Browser = new WebViewBrowserChromium()    // Use Edge Chromium (requires MS Edge Webview2 be installed)

}) ;
2 Likes