AzureAD / microsoft-authentication-library-for-dotnet

Microsoft Authentication Library (MSAL) for .NET

Home Page:https://aka.ms/msal-net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Bug] Working with CoreWebView2 in MAUI Blazor (hybrid) in combination with Identity results in compile errors

edwinvandriel opened this issue · comments

Hi,

I'm building a Maui blazor (hybrid) application. To handle some browser (webview) permissions I'm using a custom DialogPermissionRequestHandler which uses CoreWebView2, CoreWebView2PermissionRequestedEventArgs and some enumerations.
All this to make the camera working from blazor hybrid and works fine.

When I'm adding the Microsoft.Identity.Client nuget package version 4.46.0 my application breaks.
Here are the lines from the build log:


.\Platforms\Windows\SilentPermissionRequestHandler.cs(8,43,8,55): error CS0433: The type 'CoreWebView2' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\SilentPermissionRequestHandler.cs(8,64,8,104): error CS0433: The type 'CoreWebView2PermissionRequestedEventArgs' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\IPermissionRequestHandler.cs(5,36,5,48): error CS0433: The type 'CoreWebView2' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\IPermissionRequestHandler.cs(5,57,5,97): error CS0433: The type 'CoreWebView2PermissionRequestedEventArgs' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\DialogPermissionRequestHandler.cs(16,49,16,61): error CS0433: The type 'CoreWebView2' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\DialogPermissionRequestHandler.cs(16,70,16,110): error CS0433: The type 'CoreWebView2PermissionRequestedEventArgs' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\DialogPermissionRequestHandler.cs(45,49,45,75): error CS0433: The type 'CoreWebView2PermissionKind' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\DialogPermissionRequestHandler.cs(10,37,10,63): error CS0433: The type 'CoreWebView2PermissionKind' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

.\Platforms\Windows\DialogPermissionRequestHandler.cs(10,65,10,92): error CS0433: The type 'CoreWebView2PermissionState' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'


When I remove the nuget package everything works again.

Looks like Identity package introduces these WebView2 classes but from other libraries.
The custom permission handler I used are from this sample https://github.com/MackinnonBuck/MauiBlazorPermissionsExample

Yes on net6-windows10... target framework, MSAL references:

image

We are planning to remove this reference, but I do not have an ETA. It should be possible to force your app to use the exact reference.

Do you or somebody else know how I can force to use the exact reference?

See https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/dependencies

You can try to reference the version you need directly in your project, at the top level, for the windows target framework (net6-windows10..)

I just want to leave out the Microsoft.Web.WebView2.Core assemblies from the reference
I've tried some things from the link you've mentioned but without any luck.
An example on how to do this would be appreciated.

@SameerK-MSFT was looking to create a MAUI + B2C + Blazor sample and may be able to help.

I can think of a workaround. Instead of referencing MSAL's net5-windows10 version, you can force reference a different target, i.e. the netcoreapp2.1 target.

Something like

<ItemGroup>

    <PackageReference Include="Microsoft.Identity.Client" ExcludeAssets="all" GeneratePathProperty="true" Version="4.46.0"/>

    <Reference Include="Microsoft.Identity.Client" >

      <HintPath>$(PkgMicrosoft_Identity_Client)\lib\netcoreapp2.1\Microsoft.Identity.Client.dll</HintPath>

    </Reference>

  </ItemGroup>
commented

Microsoft.Identity.Client references Microsoft.Web.WebView2 since v4.28.0.
Therefore, libraries that reference this library (such as Microsoft.Graph, Microsoft.Data.SqlClient, and so on) are not compatible with WinUI 3.0.

Interesting, thanks for the update @aetos382 ... We do have a WinUI 3.0 sample and we have tested it with MSAL and did not see any error. Can you provide some repro steps?

commented

https://github.com/aetos382/WinUIApp

This repository contains a simple WinUI 3 app.
I just created an empty WinUI 3 app in VS 2022, placed WebView2 into the MainWindow, and added the Microsoft.Data.SqlClient package to the reference.
When I build this project, I get the following error.

error CS0433: The type 'CoreWebView2' exists in both 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e' and 'Microsoft.WinUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=de31ebe4ad15742b'

If I remove the reference to the Microsoft.Data.SqlClient package from the project, or downgrade its version to v4.x, I will be able to build it.
This is because v5.x of the Microsoft.Data.SqlClient package requires the Microsoft.Identity.Client package v4.45 or later, which references the Microsoft.Web.WebView2 package.

I have the same issue when using Microsoft.Identity.Client in a WinUIproject.

The problem arises when making a self contained WinUI application. @bgavrilMS did you make a packaged WinUI app? Because then you would not see the problem.

Based on the comment from @aetos382 I downgraded "Microsoft.Identity.Client" to version 4.27.1 and "Microsoft.Identity.Client.Extensions.Msal" to version 2.18.0 and it not works.

Any news on this? it is absolutely ridiculous that Microsoft.Identity.Client breaks WinUi entirely.

@rossirpaulo - correct me if I am wrong, but the scenario is broken if you use MSAL and WebView2 in a WebUI application?

The only workaround I can think of is to force target MSAL's net6 dll instead of net6-windows10.0.17763 - like described here - https://duanenewman.net/blog/post/a-better-way-to-override-references-with-packagereference/

CC @pmaytak as you are looking at cleaning up some references and @SameerK-MSFT as on-call enginner

Or any other package that includes a version of WebView2. So, for instance, any WinUi desktop (native) application currently breaks when using Microsoft.Identity.Client too; That's because the Windows SDK and Identity.Client both have references to WebView2. The problem is that there's no way to exclude a sub-package from a package; and that is exactly what we need to do to make it work in case of the Identity.Client NuGet reference -- as the WebView2 package is referenced therein.

Did you try to follow this article that explains how to deal with diamond dependencies? https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/dependencies

Is the problem that the 2 versions of WebView2 SDK are incompatible with each other?

The doubly referenced context means two DLLs are created on compilation; an error is announced on evidence of this duplication.

(versioning is not necessarily the problem; in my case, they have the same version)

Any news on this!?!

I did research on this issue. A few points:

  • The error does not occur on MAUI or MAUI Blazor project

  • The provided sample https://github.com/aetos382/WinUIApp is a WinUI project and when it has WebView2 control and Microsoft.Identity.Client package, it produces the compilation error.

  • This compiler error started occurring with version 4.28.0 i.e. it has been occurring since 03/18/2021 i.e. for almost 2 years.

I tried the avenues mentioned in the comments including:

  • Using HintPath
  • Changing the version range

The original bug is in [WindowsAppSDK] (MicrosoftEdge/WebView2Feedback#1921)

Here is the workaround

Hope this helps.

Thanks for the research @SameerK-MSFT. @rossirpaulo @aetos382 @ancker1 - can you please try the workaround provided ?

We're going to keep this open until a solution is found or the bug is officially rejected by Windows team. Please the workaround found by @SameerK-MSFT

microsoft/microsoft-ui-xaml#5689 (comment)

@bgavrilMS : posted work around does not work (I really, really tried).

Here is a simple demo app showing that the work around does not work: https://github.com/baskren/WinUi3_MSAL_SelfContained_WorkAround_Fail

Here is a simple demo app illustrating the original failure:
https://github.com/baskren/WinUi3_MSAL_SelfContained_Fail

I am not sure there is anything we can do about it. The WinUI team has stated that it's a problem on their end, but I am not sure they will fix it as it's been there for a while :(.

If you can think of a workaround, happy to discuss.

@bgavrilMS : Thank you for taking the time to respond. Sincerely appreciated.

Closing as workaround exists.

Workaround exists? Please share!

the workaround does not work. Maui is a joke. So many reference issues and double reference and bullshit. Cant believe they shipped this framework, nothing on it has worked since it was released. It takes four times as long to sort out all the issues than it does actually creating a project. What a joke microsoft.

Reopening issue.

Before this issue is closed again, would it be possible to post a POC demo project? AFAIK, every claimed work around or fix may have been successful for one person but, for me, it has not. Have a POC project would be helpful in many ways.

Before this issue is closed again, would it be possible to post a POC demo project? AFAIK, every claimed work around or fix may have been successful for one person but, for me, it has not. Have a POC project would be helpful in many ways.

I am in the same situation.

@pmaytak @localden - this will be most likely fixed by dropping the dependency on WebView2 from MSAL on netX-windows tfm, which we were planning to do...

@pmaytak - can you post the msbuild workaround maybe?

commented

@pmaytak @localden - this will be most likely fixed by dropping the dependency on WebView2 from MSAL on netX-windows tfm, which we were planning to do...

@pmaytak - can you post the msbuild workaround maybe?

This is the way to use different MSAL binary (make sure to remove explicit reference to WebView2):

<ItemGroup>
    <PackageReference Include="Microsoft.IdentityModel.Abstractions" Version="7.0.2" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.56.0" ExcludeAssets="All" GeneratePathProperty="true" />

    <Reference Include="Microsoft.Identity.Client">
      <HintPath>$(PkgMicrosoft_Identity_Client)\lib\net6.0\Microsoft.Identity.Client.dll</HintPath>
    </Reference>
  </ItemGroup>

It worked - the app compiled and ran. I am a bit surprised it worked because, as I understand, the dependency resolution is done earlier, before the binaries are copied, and in other scenarios when I used this workaround, Visual Studio still resolved the unneeded extra dependencies.

Interestingly, when I used ExcludeAssets="Compile" instead of All, I got the below error (which doesn't happen on other platforms):

Error	APPX1101	Payload contains two or more files with the same destination path 'Microsoft.Identity.Client.dll'. Source files: 
..\.nuget\packages\microsoft.identity.client\4.56.0\lib\net6.0\Microsoft.Identity.Client.dll
..\.nuget\packages\microsoft.identity.client\4.56.0\lib\net6.0-windows7.0\Microsoft.Identity.Client.dll
...\nuget\packages\microsoft.windowsappsdk\1.4.231008000\buildTransitive\Microsoft.Build.Msix.Packaging.targets	

If this workaround doesn't work for folks, we can remove the WebView2 reference, but at the end of the day the cause is within the WindowsAppSDK.

@pmaytak : you stated that the "the app compiled and ran". I have had the same experience - with DEBUG builds. But, when I went to do a RELEASE build (or PUBLISH), it would not work. In particular, when targeting ARM64.

  1. Were you able to successfully compile and run RELEASE builds?
  2. Were you able to do so when targeting ARM64 ?

Thank you for sharing what you've learned!

commented

The app compiles and runs on Debug and Release. It also publishes as self-contained successfully, but it crashes when I run it. I get an error, which maybe not be related since, it crashes without MSAL dependency also.

Description: The process was terminated due to an unhandled exception.
Exception Info: System.DllNotFoundException: Unable to load DLL 'Microsoft.ui.xaml.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)

I used this project to repro: #3583 (comment). Just replaced SqlClient with MSAL reference instead.

I don't have ARM device, so can't test that.

I have the same issue after updating Azure.Identity (1.10.4) to a WinU3 packaged project

Azure.Identity must be updated to fix a critical security issue and we must use the newest Microsoft.Identity.Client 4.56.0 MSAL library.

But if you update Microsoft.Identity.Client to 4.56.0 or 4.57.0 you have the Microsoft.Web.WebView2.Core error.

Payload contains two or more files with the same destination path 'Microsoft.Web.WebView2.Core.dll'.

So now we have critical security issue in our project due to this issue

@bgavrilMS is there any plan to fix the issue ?

We don't know how to fix this @massej, short of dropping support for net6-windows, but this is a breaking change which we are not prepared to take ASAP. A breaking change will likely take 3-6 months to get out. Note that MSAL has been on version 4.x for more than 3 years.

In pure net6, webview2 is not dependency.

CC @localden - maybe we should go the blog post route and take this change in a 4.x version and appologise?

Hi all, this is really not good.
I had a working set of applications in .net6. After I switched to .net 7 I could not anymore publish maui hybrid blazor, I get this above same error. I invested 2 days for finding some workaround but had to admit defeat. I confirmed yesterday with these steps:
-new maui hybrid blazor project, no external dependencies to any of my other projects
-added these three dependencies
"Microsoft.EntityFrameworkCore" Version="7.0.15"
"Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.15"
"Microsoft.EntityFrameworkCore.Design" Version="7.0.15"
-changed the FetchData.razor just to reference something from ef core, I am never sure if when publishing if the compiler is smart enough to skip not used dependencies

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
        Console.WriteLine(xxx.ContextId);
    }

    private MyCtx xxx = new MyCtx();

    class MyCtx : DbContext
    {
        
    }
}

After this I can not publish, with the WebView2.Core error.
So essentially I can not use EF Core 7, and I suppose 8, inside maui hybrid blazor. I am pretty sure I have seen a microsoft tutorial on how to create such project.
Not good.
I can workaround my problem, because luckily I have split things with a proper backend project and I was just referencing it for some dto classes, but if I need a simpler project without additional project for backend, with maui hybrid blazor I could not do it

This is still a problem for me. Anyone who have a good workaround?

I have identified a workaround that made my project work. It is not optimal, but it is the only working workaround I have found.

microsoft/microsoft-ui-xaml#5689 (comment)

I have identified a workaround that made my project work. It is not optimal, but it is the only working workaround I have found.

microsoft/microsoft-ui-xaml#5689 (comment)

For those that intend to use a WebView2 component in XAML will still have the error. A workaround to use WebView2 while also using this library can instantiate it through the code-behind file.

Xaml:

        <ContentControl Name="WebViewParentControl"
                            Grid.Row="1"
                             Grid.ColumnSpan="2"
                             HorizontalAlignment="Stretch"
                             VerticalAlignment="Stretch"/>

Xaml.cs:

public sealed partial class WebServerPage : Page
{
    private readonly WebView2 _webView;

    public WebServerPage()
    {
        ViewModel = App.GetService<WebServerViewModel>();
        InitializeComponent();

        _webView = new WebView2();

        Loaded += SetInitialWebViewSize;
        WebViewParentControl.SizeChanged += ResizeWebView;
    }

    private void SetInitialWebViewSize(object _, RoutedEventArgs e)
    {
        // We need to set the size here since the property `ActualWidth/Height` is 0 in the `OnNavigatedTo`
        _webView.Width = WebViewParentControl.ActualWidth;
        _webView.Height = WebViewParentControl.ActualHeight;
    }

    private void ResizeWebView(object _, SizeChangedEventArgs e)
    {
        // We manually resize, since there is an error preventing using Horizontal/VerticalAlignment = Stretch.
        _webView.Width = e.NewSize.Width;
        _webView.Height = e.NewSize.Height;
    }

    public WebServerViewModel ViewModel { get; }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        InitWebView();
    }


    private void InitWebView()
    {
        // Set the URL here you want to display in the WebView component.
        _webView.Source = new Uri(ViewModel.WebServerUrl);
       // Se the content of the ContentControl to the WebView
       // I have experienced a weird error (or maybe I am using it wrong) where the size of the webview will be height=0, width=0.
       // To work around this I manually set the size of the webview in the above functions.. Not optimal, but a quick fix.
        WebViewParentControl.Content = _webView;
    }
}

Should have been fixed in MSAL 4.61.0+

@bgavrilMS 4.61.3 still fails to compile with Payload contains two or more files with the same destination path 'Microsoft.Web.WebView2.Core.dll'.

Above error is fixed by using <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.240701003-experimental2" /> see microsoft/microsoft-ui-xaml#5689 (comment). However authentication fails on runtime due to missing webview2 assembly as the version in Microsoft.WindowsAppSDK is newer than MSAL

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e'. The system cannot find the file specified.
File name: 'Microsoft.Web.WebView2.Core, Version=1.0.864.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e'
   at Microsoft.Identity.Client.Desktop.WebView2WebUi.WebView2WebUiFactory.IsWebView2Available()
   at Microsoft.Identity.Client.Desktop.WebView2WebUi.WebView2WebUiFactory.CreateAuthenticationDialog(CoreUIParent coreUIParent, WebViewPreference useEmbeddedWebView, RequestContext requestContext)
   at Microsoft.Identity.Client.Internal.AuthCodeRequestComponent.CreateWebAuthenticationDialog()
   at Microsoft.Identity.Client.Internal.AuthCodeRequestComponent.FetchAuthCodeAndPkceVerifierAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.GetTokenResponseAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<>c__DisplayClass11_1.<<RunAsync>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.Identity.Client.Utils.StopwatchService.MeasureCodeBlockAsync(Func`1 codeBlock)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenInteractiveParameters interactiveParameters, CancellationToken cancellationToken)

Is there a way to override which version of webview should be used?