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

Custom dumps / msgpack #135

Closed Tronic closed 2 years ago

Tronic commented 2 years ago

I cannot find any option to change the dumps function. It would be much easier to use msgpack so that bytes/arraybuffer are automatically preserved, in contrast to json which needs base64 handling for binary fields. The .dict() accessor doesn't work for this because field names are in snake case then.

MasterKale commented 2 years ago

Hmm, to understand your use case better, can you confirm you're aiming for a camelCase'd representation of PublicKeyCredentialRequestOptions (for example) but with the various bytes values as bytes instead of encoded as base64url?

MasterKale commented 2 years ago

What about something like this?

from webauthn import generate_authentication_options

auth_options = generate_authentication_options(rp_id="example.com")
print(auth_options.dict(by_alias=True))

# {
#   'challenge': b'x\x16\x07\x8a\x83M\xbeI\xe8K\xc8\x90F\xe1qgn\xa3\x96\x8dg\xc3(\xd0y\x1c\xac\x9a._\xdbQ\xf7\xd4rZu\xfa$:\xbb\xd1\xa2\xa5!\xcb\x84X#P\x80\x1by\xa4 \xb3\x96!\xe85`0&\x90',
#   'timeout': 60000,
#   'rpId': 'example.com',
#   'allowCredentials': [],
#   'userVerification': <UserVerificationRequirement.PREFERRED: 'preferred'>
# }
Tronic commented 2 years ago

Seems to be working beautifully, this eliminated a lot of boilerplate code :)

ws.send(msgpack.packb(auth_options.dict(by_alias=True))

Python server to browser JS

const auth_options = MessagePack.decode(await ws.arecv())
const credentials = await navigator.credentials.create({publicKey: auth_options})

Just Works™️