Monday, March 15, 2021

WPF: External Login with Identity Server using Microsoft Edge WebView2

In this post, let's see how we can use Microsoft Edge WebView2 in a WPF Application to Sign In with an IdentityServer. This is inspired by the sample project available at IdentityModel/IdentityModel.OidcClient.Samples/WpfWebView where it's using WebBrowser. I wasn't happy with the appearance at all.

Not Responsive
Not Responsive
I thought of trying with WebView2 instead of WebBrowserWebView2 uses Microsoft Edge (Chromium) as the rendering engine whereas WebBrowser uses Internet Explorer.

So I have created a WPF Application targetting .NET 5 (please check WebView2 supported frameworks/platforms of here) and tried the code in IdentityModel/IdentityModel.OidcClient.Samples/WpfWebView project. But since I am going to be using WebView2, I have installed Microsoft.Web.WebView2 NuGet package and changed the WpfEmbeddedBrowser class as follows.

WpfEmbeddedBrowser.cs
public class WpfEmbeddedBrowser : IBrowser
{
    private BrowserOptions _options = null;

    public async Task<BrowserResultInvokeAsync(BrowserOptions optionsCancellationToken cancellationToken = default)
    {
        _options = options;

        var semaphoreSlim = new SemaphoreSlim(0, 1);
        var browserResult = new BrowserResult()
        {
            ResultType = BrowserResultType.UserCancel
        };

        var signinWindow = new Window()
        {
            Width = 800,
            Height = 600,
            Title = "Sign In",
            WindowStartupLocation = WindowStartupLocation.CenterScreen
        };
        signinWindow.Closing += (se) =>
        {
            semaphoreSlim.Release();
        };

        var webView = new WebView2();
        webView.NavigationStarting += (se) =>
        {
// Check whether we are navigating back to the RedirectUri specified in OidcClientOptions, // that means authentication process is completed
            if (IsBrowserNavigatingToRedirectUri(new Uri(e.Uri)))
            {
                e.Cancel = true;

                browserResult = new BrowserResult()
                {
                    ResultType = BrowserResultType.Success,
                    Response = new Uri(e.Uri).AbsoluteUri
                };

                semaphoreSlim.Release();
                signinWindow.Close();
            }
        };

        signinWindow.Content = webView;
        signinWindow.Show();

        // Explicit initialization
        await webView.EnsureCoreWebView2Async(null);

        // Delete existing Cookies so previous logins won't remembered
        webView.CoreWebView2.CookieManager.DeleteAllCookies();

        // Navigate
        webView.CoreWebView2.Navigate(_options.StartUrl);

        await semaphoreSlim.WaitAsync();

        return browserResult;
    }

    private bool IsBrowserNavigatingToRedirectUri(Uri uri)
    {
        return uri.AbsoluteUri.StartsWith(_options.EndUrl);
    }
}
Note: we need to have WebView2 Runtime installed on client machines for this to work.

And now when I ran the application, it's just beautiful. And works great with IdentityModel.OidcClient.
Responsive UI
Responsive UI
Seems Microsoft Edge WebView2 is the way to go if we are embedding web technologies (HTML, CSS, and JavaScript) in native apps.

Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment