davidearl / webauthn

An implementation of webauthn in PHP on the server side (e.g Yubico 2 and Google Titan keys)
https://webauthn.davidearl.uk
MIT License
129 stars 24 forks source link

How to manage multiple authenticators per user? #36

Closed marciuz closed 4 years ago

marciuz commented 4 years ago

I don't know if the question is about the library or I have to manage this at implementation level, but isn't clear for me how to manage multiple devices.

For example, if I have to store for the same user the data about a mobile (with fingerprint) AND my macbook (with fingerprint) for the same user, how to manage it?

I read the protocol allows multiple authenticators, but in this library I cannot do it.

Thanks

davidearl commented 4 years ago

The library does support this and I am using it successfully in this way in more than one website.

You have to store the key information with the user account in your database. The example uses a trivial file system, but you will most likely have a database with a users table, and you need a full text field to store the keys, which are a JSON string.

When calling register(), as well as the info for the registration in progress, you also pass in the current keys field from the user as the second parameter - this parameter can be NULL if you don't have any yet, but otherwise it is a string. The function returns an amended string (representing a set of keys) which you store back in the user keys field in the database. (If you look at the JSON it manages, you'll see it is an array, each element of which is a different key for the user).

When calling authenticate() you pass in the user keys field (again second parameter) and it attempts to authenticate against any of they keys they have registered.

If you use it for 2FA instead of login, the procedure is exactly the same, except that you would have already verified them against a (strongly-hashed) password by the time you do the authenticate() call.

marciuz commented 4 years ago

Hi David,

thanks for the quick answer and the solution. I was wrong because every time I started the webauthnkeys again. I changed the initialization in this way and now it's okay.

Best regards

if(empty($user)) {
                $data = [
                    'name' => $username,
                    'id' => md5(time() . '-' . rand(1, 1000000000)),
                    'webauthnkeys' => $webauthn->cancel(),
                ];
            }
            else{
                $data = [
                    'name' => $username,
                    'id' => $user->id,
                    'webauthnkeys' => $user->webauthnkeys,
                ];
            }