Open s21-himesh opened 10 months ago
I believe this is directly related to #380
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;
<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\":\"driver@driver.com\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"driver@driver.com\"},\"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()}";
}
}
}
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\":\"driver@driver.com\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"driver@driver.com\"},\"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
?
@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.
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.
Deployed to web app and the same result
`
private readonly static FidoBlazorSerializerContext context = new FidoBlazorSerializerContext();
string jsonData = "{\"rp\":{\"id\":\"test.azurewebsites.net\",\"name\":\"WebAuthn\",\"icon\":\"https://test.azurewebsites.net/\"},\"user\":{\"name\":\"driver@driver.com\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"driver@driver.com\"},\"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(jsonData, typeof(CredentialCreateOptions), context);
exception = $"worked as expected {JsonSerializer.Serialize(deviceResponse)}";
}
catch (Exception ex)
{
exception = $"failure {ex.ToString()} | {jsonData}";
}
}
`
This issue looks similar to https://github.com/dotnet/runtime/issues/81709.
@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).
@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?
@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?
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.
@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.
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/
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.
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.
@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.
For anyone else who hits this issue I've updated the repo available at https://github.com/s21-himesh/WebAuthnIssue with the work around.
Following code, client side, throwing exception.
Code
@page "/" @using System.Text.Json; @using Fido2NetLib;
<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\":\"driver@driver.com\",\"id\":\"ZHJpdmVyQGRyaXZlci5jb20\",\"displayName\":\"driver@driver.com\"},\"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;
}
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.ReflectionJsonTypeInfo
1[[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.1[[Fido2NetLib.PublicKeyCredentialRpEntity, Fido2.Models, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]].TryWrite(Utf8JsonWriter , PublicKeyCredentialRpEntity& , JsonSerializerOptions , WriteStack& ) at System.Text.Json.Serialization.Metadata.JsonPropertyInfo
1[[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.JsonConverter
1[[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.JsonConverter
1[[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& , JsonTypeInfo
1 ) 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?