VisualReCode / Cocoon

An implementation of the Strangler Fig pattern for ASP.NET Core
Apache License 2.0
62 stars 10 forks source link

Error `Failed to deserialize ReCode.Cocoon.Proxy.Authentication.MessagePrincipal` on Blazor Server NET6 #17

Closed conficient closed 3 years ago

conficient commented 3 years ago

Trying out Cocoon with a Blazor Server using NET 6 with

    <PackageReference Include="ReCode.Cocoon.Proxy" Version="1.0.15-beta1" />
    <PackageReference Include="ReCode.Cocoon.Proxy.BlazorServer" Version="1.0.15-beta1" />

This is pointing at a plain AspNet Webforms site. Getting the error:

2021-11-11T12:27:23.1887908+00:00 0HMD51QDOHLGG:00000001 [ERR] Failed to deserialize ReCode.Cocoon.Proxy.Authentication.MessagePrincipal value. (d55bba89)
MessagePack.MessagePackSerializationException: Failed to deserialize ReCode.Cocoon.Proxy.Authentication.MessagePrincipal value.
 ---> MessagePack.MessagePackSerializationException: Unexpected msgpack code 239 (negative fixint) encountered.
   at MessagePack.MessagePackReader.ThrowInvalidCode(Byte code)
   at MessagePack.MessagePackReader.ReadArrayHeader()
   at MessagePack.Formatters.ReCode_Cocoon_Proxy_Authentication_MessagePrincipalFormatter1.Deserialize(MessagePackReader& reader, MessagePackSerializerOptions options)
   at MessagePack.MessagePackSerializer.Deserialize[T](MessagePackReader& reader, MessagePackSerializerOptions options)
   --- End of inner exception stack trace ---
   at MessagePack.MessagePackSerializer.Deserialize[T](MessagePackReader& reader, MessagePackSerializerOptions options)
   at MessagePack.MessagePackSerializer.DeserializeFromSequenceAndRewindStreamIfPossible[T](Stream streamToRewind, MessagePackSerializerOptions options, ReadOnlySequence`1 sequence, CancellationToken cancellationToken)
   at MessagePack.MessagePackSerializer.DeserializeAsync[T](Stream stream, MessagePackSerializerOptions options, CancellationToken cancellationToken)
   at ReCode.Cocoon.Proxy.Authentication.CocoonAuthenticationClient.DeserializePrincipal(Stream stream)
   at ReCode.Cocoon.Proxy.Authentication.CocoonAuthenticationClient.AuthenticateAsync(HttpRequest request)

This is followed by

2021-11-11T12:27:23.1941785+00:00 0HMD51QDOHLGG:00000001 [INF] "Cocoon" was not authenticated. Failure message: "Failed to deserialize ReCode.Cocoon.Proxy.Authentication.MessagePrincipal value." (48071232)

Running on Windows 10, and the Blazor Server app is using Kestrel. I tried using IIS Express for the Blazor app but it does not run, so not sure what the issue is.

ThatRendle commented 3 years ago

Hi. Have you installed the Recode.Cocoon.Legacy package into the WebForms app?

conficient commented 3 years ago

Yes I have got Recode.Cocoon.Legacy in the WebForm app..

I've removed the Cocoon NUGET packages from the Blazor app, copied in the current projects (ReCode.Cocoon.Proxy and ReCode.Cocoon.Proxy.BlazorServer) from the repo and linked by project references to the Blazor app.

I found that updating the MessagePack version to 2.3.85 cured the problem. I'll leave the issue open for now until I've got the auth working on the Blazor side.

conficient commented 3 years ago

Thanks for the help so far Mark.

So I have the Blazor Server app working and routes on the WebForm app are being returned correctly. If the user logged into the WebForm app, it shows the correct WebForm content for the authorised user. I've reverted to Blazor Server for .NET 5 for the present to try to get it working.

I've created an <AuthorizeView> on my Index.razor page but it always shows <NotAuthorized> content, suggesting the Blazor authentication isn't recognising the WebForms auth.

The WebForm app is old-school so has the .ASPXAUTH cookie - I set this value in appsettings.json (as below)

    "Authentication": {
      "BackendApiUrl": "https://localhost:44300/facadeauth",
      "LoginUrl": "/Login?ReturnUrl={{ReturnUrl}}",
      "Cookies": [
        ".ASPXAUTH" /* was AuthCookie*/
      ]
    },

The Startup.cs file has the relevant setup code:

            // services.AddCocoonSession();
            services.AddCocoonCookies();

            services.AddAuthentication(CocoonAuthenticationDefaults.Scheme).AddCocoon();

            // add custom Cocoon auth
            services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
            services.AddCocoonProxy(configuration);

            // lines omitted... 
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapCocoonProxy();
                endpoints.MapFallbackToPage("/_Host");
            });

The app doesn't use sessions so this is commented out.

I can see the .ASPXAUTH cookie in the requests via Blazor so it's being passed in. Any suggestions?

conficient commented 3 years ago

I've just realised the CustomAuthenticationStateProvider is probably a placeholder class, have copied over the CocoonAuthStateProvider from the WASM project. I can get WingTip toys sample with BlazorServerCocoon correctly seeing the authentication state now.

I note WingTip is using the .AspNet.ApplicationCookie cookie.. does this mean older apps using .ASPXAUTH cookies won't work?

conficient commented 3 years ago

Understanding level now increased over the last few days..

The legacy app I'm looking to port is still using ASP.NET Membership for authentication.. hence the .ASPXAUTH cookie. So first I need to upgrade this to ASP.NET Identity before it will work correctly with Cocoon. It's a heavily customised Membership implementation so taking a while for me to do this!

I did get a test Web to work with Blazor Server on .NET 6, so it's hopefully once I have upgraded to ASP.NET Identity, I can try a new Cocoon implementation on it.

On a side note, this project would be good to showcase on the ASP.NET Community Standup - it's a great solution for users who have large WebForm apps and cannot go down the big-bang rewrite path. My app has 380 .aspx pages, of which at least 126 need to be upgraded and 97 need evaluation!

conficient commented 3 years ago

Update: finally finished converting my WebForms to use Identity, and Coccon working !