Closed variable closed 3 years ago
Here is what I found, the following js code gets the credential, I added 2 console logs to display the user handle
const result = await navigator.credentials.get({ publicKey })
fido2SuccessAuthenticationCallback(result)
function fido2SuccessAuthenticationCallback(assertion) {
const form = document.getElementById(DJANGO_FIDO_FORM_ID)
form.client_data.value = _arrayBufferToBase64(assertion.response.clientDataJSON)
form.credential_id.value = _arrayBufferToBase64(assertion.rawId)
form.authenticator_data.value = _arrayBufferToBase64(assertion.response.authenticatorData)
form.signature.value = _arrayBufferToBase64(assertion.response.signature)
console.log(assertion.response);
console.log(_arrayBufferToBase64(assertion.response.userHandle))
if (assertion.response.userHandle !== undefined) {
form.user_handle.value = _arrayBufferToBase64(assertion.response.userHandle)
} else {
form.user_handle.value = ''
}
// form.submit()
}
then the base64 string can be decoded in python to get the user name
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> base64.b64decode('amxpbg==')
b'jlin'
>>> base64.b64decode('amxpbg==').decode('utf-8')
'jlin'
Having a read on the spec, I am confused
https://www.w3.org/TR/webauthn-2/#sctn-user-handle-privacy
Since the user handle is not considered personally identifying information in § 14.4.2 Privacy of personally identifying information Stored in Authenticators, the Relying Party MUST NOT include personally identifying information, e.g., e-mail addresses or usernames, in the user handle. This includes hash values of personally identifying information, unless the hash function is salted with salt values private to the Relying Party, since hashing does not prevent probing for guessable input values. It is RECOMMENDED to let the user handle be 64 random bytes, and store this value in the user’s account.
So looks like we need to generate a random string for the user.id instead of using username?
def get_user_id(self, user: AbstractBaseUser) -> str:
"""Return a unique, persistent identifier of a user.
Default implementation return user's username, but it is only secure if the username can't be reused.
In such case, it is required to provide another identifier which would differentiate users.
See https://www.w3.org/TR/webauthn/#dom-publickeycredentialuserentity-id and
https://tools.ietf.org/html/rfc8266#section-6.1 for details.
"""
return user.username
If we need to change this to return something opaque (rather than username), then we will need to record the user_handle in authenticator model.
Closing this issue because I think we need to comply with the spec and not to use username as user handle.
https://github.com/CZ-NIC/django-fido/pull/142
Sorry I only just came to realise the user_handle from the credential can be decoded back into the username, so recording the user_handle is not necessary. Sorry for mucking around, this whole FIDO thing is new to me. :(
Cheers.