Inconsistent base64 encoding/decoding via JSON
ricecake opened this issue · 6 comments
Version
0.3.1
Description
The protocol.CredentialCreation
object returned by webauthn.BeginRegistration
uses the WebauthnID
method from the webauthn.User
interface to get the Id of the user.
If this object is serialized via the encoding/json
module, the field gets serialized as base64 via base64.StdEncoding
.
Later, after registration, if the credential is sent back as part of the login process, it will be decoded as the UserHandle portion of a AuthenticatorAssertionResponse
, which has the type defined as URLEncodedBase64
, which defines a custom json marshaller which builds on base64.RawURLEncoding
.
Since these two base64 encoding aren't compatible, parsing the assertion fails and login can't proceed, specifically generating the error "Parse error for Assertion".
Reproduction
This issue can be reproduced by registering a new credential, and returning the result of BeginRegistration directly encoded as json. Finish the registration without changing or parsing the Id on the client side.
Attempt to use the credential without changing the UserHandle field after deserialzing via the standard json encoder.
Expectations
The expected behavior is that the WebauthnID as returned from the interface method would be able to make a roundtrip in this fashion without needed modification on the server or client side.
Documentation
Updating the locations that reference []byte
to use URLEncodedBase64
should do it, but there might be backwards compatibility concerns?
Line 7 in 83e3622
Line 47 in 83e3622
webauthn/protocol/assertion.go
Line 35 in 83e3622
webauthn/protocol/assertion.go
Line 65 in 83e3622
Can you try with the following edit to confirm I understand the problem accurately:
go mod edit -replace=github.com/go-webauthn/webauthn=github.com/go-webauthn/webauthn@v0.6.1-0.20230126043752-68b0aefad880
That did seem to resolve the issue.
Looking through the change in #95 , I think that for it to properly solve this issue in all cases, it would also need to replace '+' and '/' with '-' and '_' respectively.
That way it'll fully convert the standard base64 encoding used by encoding/json into the unpadded url safe encoding being used here.
The intention in #95 is to avoid compatibility issues specifically with padding, as it's reasonable to accommodate that I think. I'm willing to take a harder stance on Standard Base64 encoding as it's not permitted at all within the webauthn spec unless I'm mistaken?
Also I think your fix is still appropriate since we should only handle encoding with the web based (without padding) encoding per the spec.
Can you check #97 also solves your issue? I suspect it will. In which case I'll merge that before the others and release it as a patch.
Just to circle back and confirm: That did resolve the issue. Thanks a bunch!