duo-labs / py_webauthn

Pythonic WebAuthn 🐍
https://duo-labs.github.io/py_webauthn
BSD 3-Clause "New" or "Revised" License
856 stars 171 forks source link

Incorrect AssertionResponse userHandle verification #83

Closed Alex-Richman closed 3 years ago

Alex-Richman commented 4 years ago

In the WebAuthnAssertionResponse .verify() function, the assertion_response.userHandle attribute is incorrectly compared against the webauthn_user.username instead of webauthn_user.user_id: https://github.com/duo-labs/py_webauthn/blob/4a0f8cd1db3b7635a1951a933d5a690beedf7c50/webauthn/webauthn.py#L890

Per https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAssertionResponse .userHandle is:

The userHandle read-only property of the AuthenticatorAssertionResponse interface is an ArrayBuffer object which is an opaque identifier for the given user. Such an identifier can be used by the relying party's server to link the user account with its corresponding credentials and other data.

The same value may be found on the id property of the options.user object (used for the creation of the PublicKeyCredential instance).

Also confirmed by https://www.w3.org/TR/webauthn/#user-handle:

User Handle The user handle is specified by a Relying Party, as the value of user.id, and used to map a specific public key credential to a specific user account with the Relying Party. Authenticators in turn map RP IDs and user handle pairs to public key credential sources.

A user handle is an opaque byte sequence with a maximum size of 64 bytes. User handles are not meant to be displayed to users. The user handle SHOULD NOT contain personally identifying information about the user, such as a username or e-mail address; see §14.9 User Handle Contents for details.

Which makes userHandle the opaque user_id, not the username.

This is also evidenced by the userHandle response I receive from navigator.credentials.get() exactly matching the opaque userID I passed into navigator.credentials.create().