0

I've been struggling with this for longer than I care to admit. I am simply trying to register a new device using WebAutn. I've tried at least two different examples and have examined lots of different code. I seem to be doing everything right... but no matter what I do I keep getting the same unhelpful exception. I've scoured the web and no one else seems to be getting this exception so I really have no idea what is wrong?

In short on line newCredential = await navigator.credentials.create({publicKey: options}); I am getting this error: "exception:TypeError: Failed to execute 'create' on 'CredentialsContainer': The provided value '2' is not a valid enum value of type AttestationConveyancePreference."

Here are the PublicKeyCredentialCreationOptions are returned and that I am submitting: NOTE: Both the challenge and user.id are populated but since they are ArrayBuffer()'s they do not print.

{
    "rp": {
        "id": "someserver",
        "name": "IB-Fido2",
        "icon": null
    },
    "user": {
        "name": "fred@someserver.com",
        "id": {},
        "displayName": "Fred Sampson"
    },
    "challenge": {},
    "pubKeyCredParams": [
        {
            "type": 0,
            "alg": -7
        },
        {
            "type": 0,
            "alg": -257
        },
        {
            "type": 0,
            "alg": -37
        },
        {
            "type": 0,
            "alg": -35
        },
        {
            "type": 0,
            "alg": -258
        },
        {
            "type": 0,
            "alg": -38
        },
        {
            "type": 0,
            "alg": -36
        },
        {
            "type": 0,
            "alg": -259
        },
        {
            "type": 0,
            "alg": -39
        }
    ],
    "timeout": 60000,
    "attestation": 0,
    "authenticatorSelection": {
        "requireResidentKey": false,
        "userVerification": 1
    },
    "excludeCredentials": [],
    "extensions": null,
    "status": "ok",
    "errorMessage": ""
}

Any help or suggestions would be GREATLY appreciated!

UPDATE: Have been serializing/ deserializing objects for a while... but almost always for C# and not JavaScript... thus I was not aware of JavaScripts String Enum until I came across this issue. I saw that this was a conversion error but had mistakenly thought the Fido2NetLib had to be returning the needed object since no one else was reporting an error with it.

Thankfully Newtonsoft.Json already had extensions to do this coversion really easily which I discovered from here.

Thus in the end I had to serialize the object with StringEnumConverter() then Deserialize it back into a custom class I created from the json which was the exact same thing but with String Enum values. I needed to do it that way because passing the Json to Blazor.Interop was not working... it needed an actual object. In the end I am sure there is a cleaner way to do the conversion with String Enum's but wanting to move forward I am rolling with it for now. See:

        string url = string.Format("{0}{1}", Endpoints.UsersFidoOptions, userId);
        var options = await userRepository.FidoOptions(url);

        if (options != null)
        {
            if (options.Status != "ok")
            {
                //Error Message
            }
            else
            {
                try
                {
                    // Serialize returned options: NOTE: String Enum Converter necessary as this object has JavaScript String Enum's
                    string json = JsonConvert.SerializeObject(options, new Newtonsoft.Json.Converters.StringEnumConverter());

                    // Next Deserialize into Custom Object to Compensate for String Enum's
                    var pubKey = Newtonsoft.Json.JsonConvert.DeserializeObject<PublicKey>(json);

                    // Now Serialize the Public Key for Session Storage
                    string pkJson = JsonConvert.SerializeObject(pubKey, new Newtonsoft.Json.Converters.StringEnumConverter());

                    await sessionStorage.SetItemAsync<string>("fido2.attestationOptions", pkJson);
                    await jsRuntime.InvokeVoidAsync("blazorInterop.registerOptions", pubKey);
                }
                catch (JSException e)
                {
                    string err = e.Message;
                }
            }
        }
Anthony Griggs
  • 1,469
  • 2
  • 17
  • 39

1 Answers1

2

When this JSON was built, it is inserting the enum numerical value rather than the string value. For example, in the pubKeyCredParams all of the type value should be "public-key", not 0, attestation should be "none" instead of 0, and userVerification should be "preferred", not 1. All are defined as DOMString in the spec https://www.w3.org/TR/webauthn/.

aseigler
  • 504
  • 3
  • 7
  • I greatly appreciate your response and help! The part I am lost at is the C# Enum within the FIDO2NetLibrary is what is returning the integer value... I think I understand that JavaScript has string Enum's but how to do the conversion? Do I need to override it? Also why am I the only one who seems to be having this conversion issue... I seem to be doing something wrong, but literally pasting the code example produces the conversion/ type error?? – Anthony Griggs Apr 19 '21 at 03:47
  • 1
    I've noticed [very similar stuff](https://github.com/dotnet/runtime/issues/31081) trying to [migrate from Newtonsoft.Json to System.Text.Json](https://github.com/abergs/fido2-net-lib/pull/204). I am not sure it's 100% identical cause, as this is not really my area, but it certainly smells the same. Definitely must have string values for those, not numbers. – aseigler Apr 19 '21 at 12:10