Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make AuthenticatorAttestationResponseJSON.clientDataJSON a DOMString or USVString #2060

Closed
zacknewman opened this issue Apr 23, 2024 · 4 comments

Comments

@zacknewman
Copy link

JSON-compatible serialization must be used for clientDataJSON. This makes the ArrayBuffer a USVString for platforms whose native string encoding is UTF-8. For such platforms, it would be easier and faster to just send the data as is; and for non-UTF-8 platforms, encoding the ArrayBuffer such that it is a USVString/DOMString is better than having to encode it as a Base64URLString which itself is a subset of DOMString anyway. Is the reason AuthenticatorAttestationResponseJSON.clientDataJSON defined that way for consistency alone? Specifically that all ArrayBuffers are converted to that?

On the server side, the data needs to be decoded twice: first to transform the Base64URLString into UTF-8 data and second to transform the UTF-8 data into a JSON map; however if the data were simply a USVString/DOMString, the server would only need to decode the data once as a JSON map.

@MasterKale
Copy link
Contributor

Is the reason AuthenticatorAttestationResponseJSON.clientDataJSON defined that way for consistency alone? Specifically that all ArrayBuffers are converted to that?

Yes, the intention was to use consistent encoding of ArrayBuffer values to something that would survive transmission to the server. As clientDataJSON is bytes it made sense to treat it like any other ArrayBuffer, even though as is outlined in the spec it's handled as a UTF-8 string during response verification.

@zacknewman
Copy link
Author

Fair enough.

@emlun
Copy link
Member

emlun commented Apr 24, 2024

Adding to what @MasterKale said - critically, the encoding of clientDataJSON MUST remain byte-for-byte identical in transmission from authenticator to server so that the signature over it remains valid. Intermediate parties should not be led to believe that they can safely parse and re-serialize the JSON, because any change to it would break the signature even if the re-serialized JSON is semantically equivalent. Therefore clientDataJSON is defined as a byte array rather than a DOMString, to emphasize that intermediate parties should consider it as opaque. These are essentially the same reasons as why JWS also serializes everything as base64-encoded byte arrays even though many of the components are JSON data.

@zacknewman
Copy link
Author

zacknewman commented Apr 24, 2024

Adding to what @MasterKale said - critically, the encoding of clientDataJSON MUST remain byte-for-byte identical in transmission from authenticator to server so that the signature over it remains valid. Intermediate parties should not be led to believe that they can safely parse and re-serialize the JSON, because any change to it would break the signature even if the re-serialized JSON is semantically equivalent. Therefore clientDataJSON is defined as a byte array rather than a DOMString, to emphasize that intermediate parties should consider it as opaque. These are essentially the same reasons as why JWS also serializes everything as base64-encoded byte arrays even though many of the components are JSON data.

clientDataJSON is not the only item that must remain identical though. For example RP ID must also remain identical since a SHA-256 hash of it is matched with rpIdHash in authData; yet PublicKeyCredentialRpEntity.id is modeled as a DOMString and not ArrayBuffer. I find it more likely RP ID gets altered in transit since an RP ID only needs to be a valid domain string. For example, www.EXample.com very likely will be altered into www.example.com when sent from the server to authenticator which will cause the registration to fail. Perhaps that is an issue with how RP ID is defined; but even if the definition were improved to require the RP ID to be the result of the domain-to-ascii algorithm, it would still be essential it does not get altered and thus be modeled as an ArrayBuffer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants