Yubico / python-fido2

Provides library functionality for FIDO 2.0, including communication with a device over USB.
BSD 2-Clause "Simplified" License
432 stars 109 forks source link

Resident Key / UserHandle Authentication? #71

Closed p-ryan closed 5 years ago

p-ryan commented 5 years ago

I'm trying to get resident keys to work with the example server. I can get resident keys to work with webauthn.me but not with the example server using a YubiKey 5 NFC. I am modifying the register_begin call to pass resident_key=True

@app.route("/api/register/begin", methods=["POST"])
def register_begin():
    registration_data, state = server.register_begin(
        {
            "id": b"user_id",
            "name": "a_user",
            "displayName": "A. User",
            "icon": "https://example.com/image.png",
        },
        credentials,
        resident_key=True,
        user_verification="discouraged",
    )

and it does look like Chrome sees the resident key request by saying:

"A record of your visit to this site will be kept on your security key."

but I do not see a userHandle in the authentication response:

@app.route("/api/authenticate/complete", methods=["POST"])
def authenticate_complete():
    if not credentials:
        abort(404)

    data = cbor.decode(request.get_data())
    print("authenticate finish data:", data)

authenticate finish data: {u'credentialId': "\x17\xfbZ{\xa5\xbcB\x12\xa5\xe3\xd3'\xd7\x97\xb0\xac", u'clientDataJSON': '{"challenge":"sbtMTP_IGixS4-Ur6uNhxqpty3jfsIKN8nDzWOu_Eeg","origin":"https://localhost:10000","type":"webauthn.get"}', u'authenticatorData': 'I\x96\r\xe5\x88\x0e\x8cht4\x17\x0fdv`[\x8f\xe4\xae\xb9\xa2\x862\xc7\x99\\xf3\xba\x83\x1d\x97c\x05\x00\x00\x00\t', u'signature': '0E\x02 \x16)\xc8\x1d\x82\xac\x14\xcd\xe0\x8c\xb3\xe2s\xb2\xc1GN\x17u\t\x81R"\x96\xc7?\xbb\x8b\x10\xfa\x9c\xdd\x02!\x00\xc2\xdb\xea\x84yP\xe9\x9c\x87\x9a5\xc9G\x9fR\xd5\\x97\x97\xf7\xd1\xe5\xaa\x80\xb0>4/3\xef0\xf4'}

Am I doing something wrong?

UPDATE: I found it, had to add "userHandle" to authenticate.html:

      body: CBOR.encode({
        "credentialId": new Uint8Array(assertion.rawId),
        "authenticatorData": new Uint8Array(assertion.response.authenticatorData),
        "clientDataJSON": new Uint8Array(assertion.response.clientDataJSON),
        "userHandle": new Uint8Array(assertion.response.userHandle),
        "signature": new Uint8Array(assertion.response.signature)
      })
p-ryan commented 5 years ago

I'm able to register and authenticate usernameless through the sample server. However, I'm not able to use the client on the command line to authenticate. Looks like the client code is expecting a list of previously registered credentials, but those are optional in the usernameless flow according to the spec, right?

dainnilsson commented 5 years ago

You're referring to the fido2.client.Fido2Client class? I just pushed a commit which should fix an issue with get_assertions when called with no allow_list. Can you try the latest commit from master and see if that resolves your issue?

p-ryan commented 5 years ago

Our build system is set up to use released versions. Let me get back to this.

dainnilsson commented 5 years ago

0.7.2 is now released, which contains this fix. Please re-open this issue if your still seeing problems with the new version!

p-ryan commented 5 years ago

I tried it out with 0.7.3 and wasn't able to get it to work.