4

I am currently building out an AJAX registration endpoint for Django to allow for FIDO2 authentication (physical hardware key login). This is from following the example/documentation from Yubico's official fido2 python library.

The only dependencies are cbor.js and js-cookie. Everything server-side is working for now, however, I keep getting this JavaScript error while invoking the navigator.credentials.create method

TypeError: Failed to execute 'create' on 
'CredentialsContainer': The provided value is not of 
type '(ArrayBuffer or ArrayBufferView)'

The code:

var csrftoken = Cookies.get('csrftoken');
fetch('/register/begin', {
    method: 'POST',
    headers: {
        'X-CSRFToken': csrftoken
    }
}).then(function(response) {
    if(response.ok) {
        return response.arrayBuffer();
    }
    throw new Error('Error getting registration data!');

}).then(CBOR.decode).then(function(options) {
    console.log(options)
    //This line is not working
    return navigator.credentials.create(options);
//More code... complete registration...

I can't figure this out. Do you know whats wrong? Thanks!

Cody
  • 329
  • 4
  • 16

2 Answers2

7

I had the same problem, and the cause was that some of the pieces of data sent from the server in the response from /register/begin must be formatted as byte strings rather than unicode strings. In particular, I've found that the user_id and the credential ids have to be byte strings - assuming that you are also following Yubico's example in the server, implemented in python 3.

Also of note is that in this case I've found Firefox's error messages much more helpful than chome's.

  • 1
    Yep that's the case. Thanks for answering, I had solved this problem a few weeks ago. That pesky 'b' in front of user_id threw me off. On a side note, I will also leave this GitHub issue that addresses how to store authenticator data in a database here https://github.com/Yubico/python-fido2/issues/31 – Cody Jan 25 '19 at 22:15
1

I was having this issue as well. I ended up using the TextEncoder class to encode the challenge and the user id...

        const enc = new TextEncoder();     
        const createCredentialOptions: CredentialCreationOptions = {
        publicKey: {
          rp: rp,
          challenge: enc.encode(challenge),
          user: {
            id: enc.encode(user.id),
            name: user.name,
            displayName: user.displayName
          },
          pubKeyCredParams: pubKeyCredParams,
          ...
tjgrist
  • 71
  • 7