Reputation: 367
I'm having an issue using my JSON object in order to trigger a WebAuthn call in Javascript. On the written navigator.credentials.create() function it is expecting a publicKey object to start the initiation process.
Right now I am using JSON.parse to parse a string into an object. After the response string is parsed, I am then passing it to the webAuthn navigator.credentials.create function but I am getting an error of:
WebAuth Error: Unhandled Rejection (TypeError): Failed to execute 'create' on 'CredentialsContainer': cannot convert to dictionary.
what could be the issue? I already parsed it to be an object, where all of the newline characters are removed. How can I get this object to be reconized? Thanks!
Original response string being passed
"\"publicKey: {\\n challenge: new Uint8Array(["testnumbers"]).buffer,\\n // Relying Party:\\n rp: {\\n name: \\\"Test.com\\\",\\n id: \\\"test.com\\\"\\n },\\n // User:\\n user: {\\n id: Uint8Array.from(\\\"test\\\", function (c) { return c.charCodeAt(0) }),\\n name: \\\"[email protected]\\\",\\n displayName: \\\"[email protected]\\\"\\n },\\n pubKeyCredParams: [\\n {\\n type: \\\"public-key\\\",\\n alg: -7\\n }\\n,{\\n type: \\\"public-key\\\",\\n alg: -257\\n }\\n\\n ],\\n attestation: \\\"none\\\",\\n timeout: 60000,\\n excludeCredentials: [],\\n authenticatorSelection: {\\nuserVerification: \\\"discouraged\\\",\\nauthenticatorAttachment: \\\"cross-platform\\\"\\n}\\n};\\n\\n\""
Upvotes: 0
Views: 1038
Reputation: 3426
tl;dr: It looks like you
JSON.stringify()
'd a complex JavaScript object, complete with multiple references toUint8Array()
...
The first thing that jumps out is the lack of escaped quotes around "testnumbers"
:
"\"publicKey: {\\n challenge: new Uint8Array(["testnumbers"]).buffer,\\n
An IDE set to JavaScript language mode calls this out right away:
The quotes need their own \\\
to match the other quotes in the string.
Additionally the beginning of publicKey
is escaped, but not the end:
"\"publicKey:
If you fix those two you can at least JSON.parse()
the string, but it just becomes a long string:
> JSON.parse(foo)
'publicKey: {\n' +
' challenge: new Uint8Array(["testnumbers"]).buffer,\n' +
' // Relying Party:\n' +
' rp: {\n' +
' name: "Test.com",\n' +
' id: "test.com"\n' +
' },\n' +
' // User:\n' +
' user: {\n' +
' id: Uint8Array.from("test", function (c) { return c.charCodeAt(0) }),\n' +
' name: "[email protected]",\n' +
' displayName: "[email protected]"\n' +
' },\n' +
' pubKeyCredParams: [\n' +
' {\n' +
' type: "public-key",\n' +
' alg: -7\n' +
' }\n' +
',{\n' +
' type: "public-key",\n' +
' alg: -257\n' +
' }\n' +
'\n' +
' ],\n' +
' attestation: "none",\n' +
' timeout: 60000,\n' +
' excludeCredentials: [],\n' +
' authenticatorSelection: {\n' +
'userVerification: "discouraged",\n' +
'authenticatorAttachment: "cross-platform"\n' +
'}\n' +
'};\n' +
'\n'
And now I'm going to call out the fact that the string contains references to Uint8Array()
- did you wrap a complex JavaScript object, complete with comments, in quotes and then run it through JSON.stringify()
? JSON can't contain values like that, it's limited to primitives like strings, numbers, arrays, and objects containing properties with such values. And it may come as a surprise that JSON doesn't support comments either!
If you're generating this code server side intending to transmit it to the front end as JSON to then execute in the browser, you've got the right idea but your execution is in need of refinement.
For starters you need to encode your Uint8Array
's into something that can be encoded as a string. Base64 is such an encoding - encode your challenge
and user.id
buffer to string, include those strings in your JSON, then convert the strings back to a buffer in the browser (how you accomplish this I'll leave as an exercise to the reader, there are many ways to do so).
And if this string is being sent via a network request then I'd suggest trying to send this code as JSON instead, and by that I mean setting 'Content-Type': 'application/json'
in the header of whatever responds to the request that returns the string you're trying to transmit over. Let whatever server framework you're using handle the intricacies of sending JSON over the wire and forget about stringifying anything.
Upvotes: 2