Exception handling in u2flib #35
Description
Calling verify_authenticate
/ complete_register
can raise a bunch of different exceptions.
Here are some examples:
>>> from u2flib_server.u2f_v2 import start_authenticate, complete_register
>>> start_authenticate({})
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/u2f_v2.py", line 228, in start_authenticate
appId=device.appId,
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/jsapi.py", line 68, in __getattr__
(type(self).__name__, key))
AttributeError: 'DeviceRegistration' object has no attribute 'appId'
>>> start_authenticate('{}')
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/u2f_v2.py", line 228, in start_authenticate
appId=device.appId,
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/jsapi.py", line 68, in __getattr__
(type(self).__name__, key))
AttributeError: 'DeviceRegistration' object has no attribute 'appId'
>>> start_authenticate('banana')
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/u2f_v2.py", line 221, in start_authenticate
device = DeviceRegistration.wrap(device)
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/jsapi.py", line 76, in wrap
return data if isinstance(data, cls) else cls(data)
File "/Users/andreas/code/x/venv-2.7/lib/python2.7/site-packages/u2flib_server/jsapi.py", line 57, in __init__
self.update(json.loads(data.decode('utf-8')))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 384, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
>>>
When a signature check fails, cryptography.exceptions.InvalidSignature
is raised. How are users supposed to know to catch an exception from the underlying cryptography library?
Given that this is the reference implementation of U2F for Python servers and this is security sensitive, exceptions and error conditions should be handled better and clearer. The example server can be crashed in a number of way by provided user input. The examples should be using best practices and be crash free.
My proposal: u2flib should define its own exceptions "U2FError
" and could have different subclasses to classify input formatting errors "U2FMalformedInput
" from signature errors "U2FSignatureError
". Any exceptions that is raised from invoking u2flib that is not a "U2FError
" should be treated as a bug.