Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor WASM .net 7.0.11 build with Fido2 release 3.0.1 #446

Open
s21-himesh opened this issue Oct 13, 2023 · 17 comments
Open

Blazor WASM .net 7.0.11 build with Fido2 release 3.0.1 #446

s21-himesh opened this issue Oct 13, 2023 · 17 comments

Comments

@s21-himesh
Copy link

s21-himesh commented Oct 13, 2023

Following code, client side, throwing exception.

Code

@page "/"
@using System.Text.Json;
@using Fido2NetLib;

Webauthn Recreate Issue

<button class="btn btn-primary" @OnClick="test">Click me to recreate

@code {
string jsonData = "{"rp":{"id":"test.azurewebsites.net","name":"WebAuthn","icon":"https://test.azurewebsites.net/\"},\"user\":{\"name\":\"[email protected]\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"[email protected]\"},\"challenge\":\"QHcEA7xeJRx3_SZV4uoFQQ\",\"pubKeyCredParams\":[{\"type\":\"public-key\",\"alg\":-7},{\"type\":\"public-key\",\"alg\":-257},{\"type\":\"public-key\",\"alg\":-37},{\"type\":\"public-key\",\"alg\":-35},{\"type\":\"public-key\",\"alg\":-258},{\"type\":\"public-key\",\"alg\":-38},{\"type\":\"public-key\",\"alg\":-36},{\"type\":\"public-key\",\"alg\":-259},{\"type\":\"public-key\",\"alg\":-39},{\"type\":\"public-key\",\"alg\":-8}],\"timeout\":60000,\"attestation\":\"direct\",\"authenticatorSelection\":{\"authenticatorAttachment\":\"platform\",\"requireResidentKey\":true,\"userVerification\":\"required\"},\"excludeCredentials\":[],\"extensions\":{\"uvm\":true},\"status\":\"ok\",\"errorMessage\":\"\"}";
string exception = string.Empty;

private void test()
{
    try
    {
        var deviceResponse = CredentialCreateOptions.FromJson(jsonData);            
        exception = $"worked as expected {JsonSerializer.Serialize(deviceResponse)}";
    }
    catch (Exception ex)
    {
        exception = $"failure {ex.ToString()}";
    }       
}

}

Exception being thrown:-

System.NotSupportedException: ConstructorContainsNullParameterNames, Fido2NetLib.PublicKeyCredentialRpEntity Path: $.Rp. ---> System.NotSupportedException: ConstructorContainsNullParameterNames, Fido2NetLib.PublicKeyCredentialRpEntity at System.Text.Json.ThrowHelper.ThrowNotSupportedException_ConstructorContainsNullParameterNames(Type ) at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo1[[Fido2NetLib.PublicKeyCredentialRpEntity, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].GetParameterInfoValues() at System.Text.Json.Serialization.Metadata.JsonTypeInfo.Configure() at System.Text.Json.Serialization.Metadata.JsonTypeInfo.g__ConfigureLocked|143_0() at System.Text.Json.Serialization.Metadata.JsonTypeInfo.EnsureConfigured() at System.Text.Json.Serialization.Metadata.JsonPropertyInfo.get_JsonTypeInfo() at System.Text.Json.WriteStack.PeekNestedJsonTypeInfo() at System.Text.Json.Serialization.JsonConverter1[[Fido2NetLib.PublicKeyCredentialRpEntity, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].TryWrite(Utf8JsonWriter , PublicKeyCredentialRpEntity& , JsonSerializerOptions , WriteStack& ) at System.Text.Json.Serialization.Metadata.JsonPropertyInfo1[[Fido2NetLib.PublicKeyCredentialRpEntity, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].GetMemberAndWriteJson(Object , WriteStack& , Utf8JsonWriter ) at System.Text.Json.Serialization.Converters.ObjectDefaultConverter1[[Fido2NetLib.CredentialCreateOptions, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].OnTryWrite(Utf8JsonWriter , CredentialCreateOptions , JsonSerializerOptions , WriteStack& ) at System.Text.Json.Serialization.JsonConverter1[[Fido2NetLib.CredentialCreateOptions, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].TryWrite(Utf8JsonWriter , CredentialCreateOptions& , JsonSerializerOptions , WriteStack& ) at System.Text.Json.Serialization.JsonConverter1[[Fido2NetLib.CredentialCreateOptions, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].WriteCore(Utf8JsonWriter , CredentialCreateOptions& , JsonSerializerOptions , WriteStack& ) Exception_EndOfInnerExceptionStack at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& , NotSupportedException ) at System.Text.Json.Serialization.JsonConverter1[[Fido2NetLib.CredentialCreateOptions, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].WriteCore(Utf8JsonWriter , CredentialCreateOptions& , JsonSerializerOptions , WriteStack& ) at System.Text.Json.JsonSerializer.WriteCore[CredentialCreateOptions](Utf8JsonWriter , CredentialCreateOptions& , JsonTypeInfo1 ) at System.Text.Json.JsonSerializer.WriteString[CredentialCreateOptions](CredentialCreateOptions& , JsonTypeInfo1 ) at System.Text.Json.JsonSerializer.Serialize[CredentialCreateOptions](CredentialCreateOptions , JsonSerializerOptions ) at WebAuthnIssue.Client.Pages.Index.test()
`

Does not occur locally and only on azure app service. App service is configured for .net 7.

Any ideas how this can be resolved?

@s21-himesh
Copy link
Author

I believe this is directly related to #380

@s21-himesh
Copy link
Author

Reading the various posts I believe the following should work. Again works locally but not on app service:

@page "/"
@using System.Text.Json;
@using Fido2NetLib;

Webauthn Recreate Issue

<button class="btn btn-primary" @OnClick="test">Click me to recreate

@code {
private readonly JsonSerializerOptions _jsonOptions = new FidoBlazorSerializerContext().Options;
string jsonData = "{"rp":{"id":"test.azurewebsites.net","name":"WebAuthn","icon":"https://test.azurewebsites.net/\"},\"user\":{\"name\":\"[email protected]\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"[email protected]\"},\"challenge\":\"QHcEA7xeJRx3_SZV4uoFQQ\",\"pubKeyCredParams\":[{\"type\":\"public-key\",\"alg\":-7},{\"type\":\"public-key\",\"alg\":-257},{\"type\":\"public-key\",\"alg\":-37},{\"type\":\"public-key\",\"alg\":-35},{\"type\":\"public-key\",\"alg\":-258},{\"type\":\"public-key\",\"alg\":-38},{\"type\":\"public-key\",\"alg\":-36},{\"type\":\"public-key\",\"alg\":-259},{\"type\":\"public-key\",\"alg\":-39},{\"type\":\"public-key\",\"alg\":-8}],\"timeout\":60000,\"attestation\":\"direct\",\"authenticatorSelection\":{\"authenticatorAttachment\":\"platform\",\"requireResidentKey\":true,\"userVerification\":\"required\"},\"excludeCredentials\":[],\"extensions\":{\"uvm\":true},\"status\":\"ok\",\"errorMessage\":\"\"}";
string exception = string.Empty;

private void test()
{
    try
    {
        var deviceResponse = JsonSerializer.Deserialize<CredentialCreateOptions>(jsonData, _jsonOptions);            
        exception = $"worked as expected {JsonSerializer.Serialize(deviceResponse)}";
    }
    catch (Exception ex)
    {
        exception = $"failure {ex.ToString()}";
    }       
}

}

@joegoldman2
Copy link
Contributor

joegoldman2 commented Oct 15, 2023

I am unable to reproduce the issue with .NET 7 and the package Fido2 3.0.1 or 4.0.0-beta4

using Fido2NetLib;
using System.Text.Json;
using System.Text.Json.Serialization;

string json = "{\"rp\":{\"id\":\"test.azurewebsites.net\",\"name\":\"WebAuthn\",\"icon\":\"https://test.azurewebsites.net/\"},\"user\":{\"name\":\"[email protected]\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"[email protected]\"},\"challenge\":\"QHcEA7xeJRx3_SZV4uoFQQ\",\"pubKeyCredParams\":[{\"type\":\"public-key\",\"alg\":-7},{\"type\":\"public-key\",\"alg\":-257},{\"type\":\"public-key\",\"alg\":-37},{\"type\":\"public-key\",\"alg\":-35},{\"type\":\"public-key\",\"alg\":-258},{\"type\":\"public-key\",\"alg\":-38},{\"type\":\"public-key\",\"alg\":-36},{\"type\":\"public-key\",\"alg\":-259},{\"type\":\"public-key\",\"alg\":-39},{\"type\":\"public-key\",\"alg\":-8}],\"timeout\":60000,\"attestation\":\"direct\",\"authenticatorSelection\":{\"authenticatorAttachment\":\"platform\",\"requireResidentKey\":true,\"userVerification\":\"required\"},\"excludeCredentials\":[],\"extensions\":{\"uvm\":true},\"status\":\"ok\",\"errorMessage\":\"\"}";
var options = CredentialCreateOptions.FromJson(json);
var options2 = JsonSerializer.Deserialize<CredentialCreateOptions>(json, new FidoBlazorSerializerContext().Options);

[JsonSerializable(typeof(AssertionOptions))]
[JsonSerializable(typeof(AuthenticatorAssertionRawResponse))]
[JsonSerializable(typeof(AuthenticatorAttestationRawResponse))]
[JsonSerializable(typeof(CredentialCreateOptions))]
public partial class FidoBlazorSerializerContext : JsonSerializerContext
{
}

Are you able to commit a minimal repro and give the output of dotnet --info?

@Yomist
Copy link

Yomist commented Oct 16, 2023

@joegoldman2 did you try deploying on the app service?
where do I specify the runtime I am getting unhandled exception from loading type 'System.TypeLoadException' occurred in Unknown Module.
Could not load type 'System.Object' from assembly 'System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' because the parent does not exist.

image

@s21-himesh
Copy link
Author

Hi @joegoldman2 @Yomist

I've prepared a repo https://github.com/s21-himesh/WebAuthnIssue

I've pushed to an app service/ web app https://webauthnfido.azurewebsites.net/ so you can see the exception.

Let me know, if you need anything else.

@s21-himesh
Copy link
Author

@joegoldman2
Copy link
Contributor

This issue looks similar to dotnet/runtime#81709.

@iamcarbon
Copy link
Contributor

@s21-himesh Will you be able to update to .NET 8.0 once it's released? This will likely be fixed once we cross-target .NET8.0 (soon).

@s21-himesh
Copy link
Author

@iamcarbon ideally not as we have a released prepared and this is the last outstanding issue. Is there any workaround for this? Can anyone explain why it works local vs app service?

@s21-himesh
Copy link
Author

@Regenhardt Hi Marlon, you appear to have the same error message I'm experiencing on this ticket 81709. Can you assist with explaining how this can be resolved?

@Regenhardt
Copy link
Contributor

This can be solved using the Fido2.BlazorWebassembly lib in the frontend. It's not on NuGet yet, but you can just copy the code (or copy the whole project to your own solution, or add as submodule) and it should work. You can check the BlazorWasmDemo for an example, I believe the Program.cs has the needed setup and the UserService the actual usage.

@s21-himesh
Copy link
Author

@Regenhardt gave that a try today. Can confirm the same result where it works locally but not in the cloud. To confirm I added BlazorWebAssembly and Fido2.Models to test the concept. I removed the nuget package.

To confirm, the build is .net 7 blazor wasm.

@Regenhardt
Copy link
Contributor

To test a suspicion, locally build your app in release mode. This is what triggered the error for me: Building in release mode stripped the assembly of things it didn't understand I needed.

This was fixed by using the specific SerializerContext to tell the serializer what it needs to know. If you use the source directly, this will even use source generation to generate the serializer code, speeding up serialization.

Off topic: Love the loading circle on your demo app, does it come with the template now or do I have to steal it myself?

Also I love how we built basically the same thing to fix this, mine is still broken over there lol: https://blazor-webauthn.onrender.com/

@Regenhardt
Copy link
Contributor

As far as I can see (assuming the jsonData is correct there), your deserialisation looks ok there. I can check out the code later and try to see if there's anything else I can find.

@Regenhardt
Copy link
Contributor

I believe this will be fixed when either the Blazor lib is released as NuGet package, or all the libs are updated or multi-targeted to net7.0 for newer apps.

The models are packaged for net6.0, losing "unneeded" metadata. Here, the needed metadata is in the saved FidoBlazorSerializerContext, ready to be used for serialization.

In your case, compiling the serializer context in net7.0 creates the newer version of serialization that includes code generation. Unfortunately though, the code cannot be properly generated, as that information isn't in the NuGet package of the models.

You could of course have your app target net6.0 in order to make it use the former serialization logic, until the Fido2 lib is updated or the Blazor lib is on NuGet.

A mid point could be to add another lib to your solution that targets net6.0 and includes the serializer context, but I haven't tested this.

@s21-himesh
Copy link
Author

@Regenhardt loader is default when setting up a blazor wasm project in .net 7. I have committed to repo but think the loader is tucked away!

I did see your ticket but couldn't get any of the suggestions to work :)

I can confirm the mid point suggestion works.

@s21-himesh
Copy link
Author

For anyone else who hits this issue I've updated the repo available at https://github.com/s21-himesh/WebAuthnIssue with the work around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants