webauthn
webauthn copied to clipboard
client extension results field name is unclear
Proposed Change
https://www.w3.org/TR/webauthn-2/#idl-index
The issue with this interface is that no where in the IDL do we specify the name of the struct member that holds https://www.w3.org/TR/webauthn-2/#dictdef-authenticationextensionsclientoutputs for an attest or auth result. Because of this, it's up to implementers to "work it out" and name a member of publicKeyCredential to hold the extensions output for serialisation and transmission.
Due to this for a long time we worked quite happily with the struct member name "extensions" but MDN defines this as clientExtensionResults.
The IDL and specification needs to clearly spell out how a clientExtensionResult should be serialised and to what value name it is attached to.
The only hint that this field might be named clientExtensionResult is here:
https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion
Let clientExtensionResults be the result of calling credential.[getClientExtensionResults()](https://www.w3.org/TR/webauthn-2/#dom-publickeycredential-getclientextensionresults).
But this doesn't indicate that it is credential.clientExtensionResults, only that some nebulous clientExtensionResults value now exists and needs to be sent to the RP.
Alternately, the argument is that the communication between the javascript of the rp and the rp itself is up to the rp to define that layer, and so clientExtensionResults can be named whatever you want. This makes it harder for someone to bring their own JS to a library like webauthn-rust where they expect a standard name for this field.
An example of where we do this correctly is https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialrequestoptions which clearly spells out what dict member the extensions requests belongs to.
https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/toJSON
This may already be somewhat resolved by the editors draft where the toJSON interface defines this, but we still should resolve this for users who don't call the toJSON interfaces.
I believe there are similarities to getTransports() where the API contract is not expressly important to the WebAuthn spec due to the space it sits in. The only difference is that the result of getTransports() is serialized in the credential record, and in the instance of the output of getClientExtensionResults() there is not a direct necessity to store the output.
In effect the WebAuthn spec is not concerned with how a RP handles the storage or communication of the output of getClientExtensionResults() because it's not important, the only important factor is the means and steps by which the result of this function should be validated.
toJson gives precedent that we do care about this transport - else we wouldn't need the browser to serialise something and make a promise about the shape of that data.
I suppose the way I look at the spec here is the interoperability of the frontend/backend is a concern for the authors of the relevant libraries/applications.
If I'm understanding you correctly, getTransports() is in a very similar boat here since it's effectively documented in the same way where how it makes it to the backend is only documented by means of the toJSON method and the internal slot accessed via getTransports().
The process I've personally followed in library data structures is to follow the format of the output of toJSON exactly, because to my way of thinking that is effectively the most logical way to guarantee high interoperability (i.e. in this instance the field name is communicated as clientExtensionResults in several places). Though that being said I've been working off the editors draft for a while with the increase in requests for level 3 related features, and anticipation that level 3 will be recommended in the near future anyway; which may have an impact.
However this would not lead me to believe that all API's must follow this convention, and interoperability layers could very well exist for this purpose as well. The data may in fact be communicated by a means that's more efficient to use something other than JSON entirely.
I cannot say I have not been frustrated by similar in the past, and I cannot say my interpretation is necessarily the correct one, but I guess at some stage it clicked for me (either correctly or incorrectly) that this doesn't need to be and potentially shouldn't be articulated because of design choices developers may want to make.
The process I've personally followed in library data structures is to follow the format of the output of toJSON exactly, because to my way of thinking that is effectively the most logical way to guarantee high interoperability (i.e. in this instance the field name is communicated as
clientExtensionResultsin several places). Though that being said I've been working off the editors draft for a while with the increase in requests for level 3 related features, and anticipation that level 3 will be recommended in the near future anyway; which may have an impact.
This is kind of my point - toJSON is standardising the format of a request to an RP, so especially for older implementations, that were supporting webauthn since L1 and onward (like webauthn-rs) this change is coming as a shock as now we have users calling toJSON then wondering why these formerly undefined struct names aren't being accepted by their webauth library.
This is why I am suggesting that we define not just toJSON, but the reverse for an RP and what they expect to see during struct parsing.