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

Separated proposed changes to extension semantics from PR #386 and use TypeError, per @jyasskin #389

Merged
merged 9 commits into from
Apr 21, 2017

Conversation

selfissued
Copy link
Contributor

Per discussions on the 22-Mar-18 WG call, these semantic changes previously part of the mbj-registries-and-extensions branch proposed as pull request #386 are now in the separate branch mbj-extension-semantics. Thanks to @jyasskin for suggesting the use of the TypeError exception.

Copy link
Contributor

@equalsJeffH equalsJeffH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied over my comments from #386

index.bs Outdated
@@ -475,7 +475,8 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If |extension| is not supported by this client platform, then [=continue=].

1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
"{{TypeError}}", and terminate this algorithm.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this adds signaling of errors from running |extension|'s [=client processing=] algorithm, and aborting of the entire makeCred() operation, where the prior behavior (whether actually good or not) is to ignore errors and go on to the next extension and not abort the overall operation.

Others e.g. @vijaybh @jcjones @jyasskin ought to weigh in on this algorithm change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me, although I don't have a strong opinion.

If an extension is critical for security, the RP needs to check for it in the response regardless, because of the previous "if not supported then continue" step. If the extension is optional, you still want some way for developers to notice that their argument is malformed and so won't work on any browser. Throwing a TypeError here is plausible. Checking the "exts" extension and then for a missing response for supported extensions would also work, but takes a lot more developer effort.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can understand the argument that a programmer error (such as a badly formed client argument to an extension) should be flagged. However, this has a couple of problems:

  1. If the specification of an extension evolves in future (e.g. extension adds a new version and the version number is given in the client argument) then this will either leak data or break an operation that could have been completed correctly by ignoring the extension.
  2. Client processing can also fail for a number of other reasons other than malformed arguments (e.g. authenticator selection not finding authenticators of the requested type). In those cases this error becomes misleading and also leaks privacy-sensitive info (which can be used to fingerprint the system).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per your point 1, Vijay, if an extension is updated in an incompatible way, I'd argue that it should instead be a new extension.

Per your point 2, I'm good with clients throwing appropriate errors when they detect errors.

The point of this change is that it's, in general, a good architectural choice to enable errors to be caught and to fail early a the time they are caught. Ignoring errors makes things hard to debug and allows incorrect code to appear to work, which is almost always a bad thing. Fail fast.

index.bs Outdated
@@ -605,7 +606,9 @@ When this method is invoked, the user agent MUST execute the following algorithm
|extension| → |argument| of <code>{{options}}.{{AssertionOptions/extensions}}</code>:
1. If |extension| is not supported by this client platform, then [=continue=].
1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
"{{TypeError}}", and terminate this algorithm.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

index.bs Outdated
set to `true` to signify that the extension was understood and processed.
Likewise, such an extension that is processed by the authenticator that does not otherwise require any result values
SHOULD also return a Boolean extension result,
set to `true` to signify that the extension was understood and processed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per prior discussion with MikeJ @selfissued, I am inclined to model the above-suggested "the extension was honored" return value as a single bit (or byte) signifying "acknowledged", i.e., a value signifying "ACK" and not as a boolean, because we never intend to return false, and that seems potentially confusing to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The choice of "true" as the suggested default extension result was to be parallel with the choice of "true" as the client argument value at https://w3c.github.io/webauthn/#extension-request-parameters. It would be puzzling to use different conventions in the same cases when the reason for these default values is the same.

@equalsJeffH
Copy link
Contributor

suggest we retitle this PR to be something like "changes to makeCred() and getAssn() extension handling"

index.bs Outdated
@@ -475,7 +475,8 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If |extension| is not supported by this client platform, then [=continue=].

1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want just "... rejected with=] a {{TypeError}}, ..."

index.bs Outdated
@@ -475,7 +475,8 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If |extension| is not supported by this client platform, then [=continue=].

1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
"{{TypeError}}", and terminate this algorithm.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me, although I don't have a strong opinion.

If an extension is critical for security, the RP needs to check for it in the response regardless, because of the previous "if not supported then continue" step. If the extension is optional, you still want some way for developers to notice that their argument is malformed and so won't work on any browser. Throwing a TypeError here is plausible. Checking the "exts" extension and then for a missing response for supported extensions would also work, but takes a lot more developer effort.

index.bs Outdated
@@ -475,7 +475,8 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If |extension| is not supported by this client platform, then [=continue=].

1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
"{{TypeError}}", and terminate this algorithm.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can understand the argument that a programmer error (such as a badly formed client argument to an extension) should be flagged. However, this has a couple of problems:

  1. If the specification of an extension evolves in future (e.g. extension adds a new version and the version number is given in the client argument) then this will either leak data or break an operation that could have been completed correctly by ignoring the extension.
  2. Client processing can also fail for a number of other reasons other than malformed arguments (e.g. authenticator selection not finding authenticators of the requested type). In those cases this error becomes misleading and also leaks privacy-sensitive info (which can be used to fingerprint the system).

index.bs Outdated
set to `true` to signify that the extension was understood and processed.
Likewise, such an extension that is processed by the authenticator that does not otherwise require any result values
SHOULD also return a Boolean extension result,
set to `true` to signify that the extension was understood and processed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph seems redundant with the preceding one.

IMO there is no such thing as an extension that is not designed to enable the RP to know if it was understood and acted on. The rest of the paragraph is just recommending returning "true" as a specific way of letting the RP know the extension was honored (the latter part was specified in the previous paragraph). If we do want to add this, it seems like it could be added to the previous paragraph.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll restructure this text as you suggest, Vijay.

index.bs Outdated
@@ -475,7 +475,7 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If |extension| is not supported by this client platform, then [=continue=].

1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
algorithm returned an error, return [=a promise rejected with=] a
"{{TypeError}}", and terminate this algorithm.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't like this. It seems to me like it is actually losing information for the developer. For instance, the appid extension's client processing is defined as "If {{AssertionOptions/rpId}} is present, reject promise with a DOMException whose name is "{{NotAllowedError}}", and terminate this algorithm." This text would catch that exception and replace it with TypeError. Why not simply terminate this algorithm and propagate the error returned from the client processing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with your suggestion to terminate the algorithm and propagate the error returned from the client processing. The main thing I was trying to achieve was to enable errors to be caught and cause the operation to fail at that time, rather than being silently ignored.

index.bs Outdated
@@ -606,7 +606,7 @@ When this method is invoked, the user agent MUST execute the following algorithm
|extension| → |argument| of <code>{{options}}.{{AssertionOptions/extensions}}</code>:
1. If |extension| is not supported by this client platform, then [=continue=].
1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, return [=a promise rejected with=] a {{DOMException}} whose name is
algorithm returned an error, return [=a promise rejected with=] a
"{{TypeError}}", and terminate this algorithm.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment about propagating the underlying error instead of masking it like this.

index.bs Outdated
@@ -2400,6 +2397,9 @@ error.
the value of |rpId| for all client processing should be replaced by the
value of |appid|.

: Client data
:: Returns the JSON value `true` to indicate to the RP that the extension was acted upon

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having this section called out explicitly is useful. However "Client data" should say how the ClientData is actually changed - that means specifying a key and a value in the JSON. In this case, the client processing already specifies such a change by replacing the rpId; maybe this section should just point out this fact. In general "true" is not useful in this context because in order to validate it the RP has to remember what it asked for in the request and verify that against the rpId in the ClientData; it can do the latter even in the absence of a "true" value here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might this be clearer if the six standard sections had these titles, rather than the current ones?

  • Client input data
  • Client processing
  • Client output data
  • Authenticator input data
  • Authenticator processing
  • Authenticator output data

What you're mostly talking about I think is client processing, rather than the client output data. Of course, you could be proposing that a particular extension, the "appid" extension, have a different return value than "true". That's fine with me. If so, make a proposal.

index.bs Outdated
@@ -2424,6 +2424,9 @@ prompt string, intended for display on a trusted device on the authenticator.
: Client processing
:: None, except default forwarding of client argument to authenticator argument.

: Client data
:: Returns the authenticator data string as JSON string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClientData (which must be hashed and fed into the authenticator for signature) cannot depend on AuthenticatorData (which comes out of the authenticator after the signature has been computed). The "Client processing" section above already defines what should happen here - the ClientData should be augmented with a key "txAuthSimple", with string value equal to the supplied client argument.

index.bs Outdated
@@ -2454,6 +2457,9 @@ allows authenticators without a font rendering engine to be used and also suppor
: Client processing
:: None, except default forwarding of client argument to authenticator argument.

: Client data
:: Returns the base64url encoding of the authenticator data value as a JSON string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClientData (which must be hashed and fed into the authenticator for signature) cannot depend on AuthenticatorData (which comes out of the authenticator after the signature has been computed). The "Client processing" section above already defines what should happen here - the ClientData should be augmented with a key "txAuthGeneric", with string value equal to the JSON serialization of the client argument.

However this extension has an additional problem: Client argument should be something passed by JavaScript, and it is defined here as CBOR. We should either define this as a CBOR string encoded in say base64, or define it as a dictionary that gets CBOR-encoded before passing to the authenticator.

index.bs Outdated

: Authenticator processing
:: None.
:: none
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editorial nit: Why omit capitalization and punctuation in this one item when others are capitalized and punctuated?

index.bs Outdated
@@ -2517,6 +2528,9 @@ This [=registration extension=] enables the [RP] to determine which extensions t
: Client processing
:: None, except default forwarding of client argument to authenticator argument.

: Client data
:: Returns the list of supported extensions as a JSON array of extension identifier strings

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClientData (which must be hashed and fed into the authenticator for signature) cannot depend on AuthenticatorData (which comes out of the authenticator after the signature has been computed). In this case it is better to include no client data since the authenticator data will reflect the option anyways.

index.bs Outdated
@@ -2541,6 +2555,9 @@ This [=registration extension=] and [=authentication extension=] enables use of
: Client processing
:: None, except default forwarding of client argument to authenticator argument.

: Client data
:: Returns a JSON string containing the base64url encoding of the authenticator data

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClientData (which must be hashed and fed into the authenticator for signature) cannot depend on AuthenticatorData (which comes out of the authenticator after the signature has been computed). TShould be "none".

index.bs Outdated
: Client data
:: Returns a JSON object that encodes the location information in the authenticator data as a Coordinates value,
as defined by [The W3C Geolocation API Specification](https://dev.w3.org/geo/api/spec-source.html#coordinates_interface).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClientData (which must be hashed and fed into the authenticator for signature) cannot depend on AuthenticatorData (which comes out of the authenticator after the signature has been computed). Should be "none".

index.bs Outdated
@@ -2644,6 +2664,9 @@ This [=registration extension=] and [=authentication extension=] enables use of
: Client processing
:: None, except default forwarding of client argument to authenticator argument.

: Client data
:: Returns a JSON array of 3-element arrays of numbers that encodes the factors in the authenticator data

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClientData (which must be hashed and fed into the authenticator for signature) cannot depend on AuthenticatorData (which comes out of the authenticator after the signature has been computed). Should be "none".

Copy link
Member

@jyasskin jyasskin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is significantly better than what was there before; thank you! I've also left several comments, but if you want to merge this and handle the comments in a separate PR, that's fine.

index.bs Outdated
@@ -454,7 +454,8 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If |extension| is not supported by this client platform, then [=continue=].

1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
algorithm returned an error, return [=a promise rejected with=] either that error or a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm skeptical of letting the UA choose which error to return, since it'll reduce interoperability. What was the reason for that? If it was a weak reason, I'd rather just unconditionally forward the client processing algorithm's error.

index.bs Outdated
authentication extensions) or {{makeCredential()}} call (for [=registration extensions=]) to the client platform. The client
platform performs additional processing for each extension that it supports, and augments the [=client data=] as required by the
extension. In addition, the client collects the authenticator arguments for the above extensions, and passes them to the
extension. In addition, the client collects the [=authenticator extension input=] values for the above extensions, and passes them to the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it that the client extension output becomes the authenticator extension input, or does the authenticator extension input come from somewhere else too? (This may be addressed farther down in the patch.)

authenticator. Since all extensions are optional, this will not cause a functional failure in the API operation.
Likewise, clients can choose to produce a [=client extension output=] value for an extension that it does not understand by encoding the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, the client extension output is created from the authenticator extension output, not from the result of the client processing steps? That wasn't clear from the discussion above. Does it mean that we need two client processing algorithms, one to process the input, and another to process the output?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the client extension output is created from the authenticator extension output, not from the result of the client processing steps?

It seems the answer is "no, see 1st parag of [[sctn-client-extension-processing]]"

Does it mean that we need two client processing algorithms, one to process the input, and another to process the output?

that seems to be addressed by the last parag of [[sctn-client-extension-processing]] in combination with section [[#sctn-authenticator-extension-processing]].

we could perhaps have better linking to the latter sections from this opening [[#extensions]] section.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The next commit will make it clear that the client processing steps take in the [=client extension input=] and produce the [=authenticator extension input=] and they also take in the [=authenticator extension output=] and produce the [=client extension output=].

index.bs Outdated
{{MakeCredentialOptions/extensions}} option to the {{makeCredential()}} or {{getAssertion()}} call. The entry key MUST be the
extension identifier, and the value MUST be the [=client argument=].
[=extension identifier=], and the value MUST be the [=client extension input=].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't introduce this problem, but we can't MUST the Relying Party in this section since that mixes conformance requirements on the UA+Authenticator vs the Relying Party. Instead, I suggest saying something like "The entry key is interpreted as the extension identifier, and the value is interpreted as the client extension input." You could omit "interpreted as" if you prefer.

index.bs Outdated

<pre class="example" highlight="js">
var assertionPromise = credentials.getAssertion(..., /* extensions */ {
"webauthnExample_foobar": 42
});
</pre>

Extension definitions MUST specify the valid values for their client argument. Clients SHOULD ignore extensions with an invalid
client argument. If an extension does not require any parameters from the [RP], it SHOULD be defined as taking a Boolean client
Extension definitions MUST specify the valid values for their [=client extension input=]. Clients SHOULD ignore extensions with a invalid
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"with an invalid"

: Client processing
:: None, except default forwarding of client argument to authenticator argument.
: Client extension processing
:: None, except creating the authenticator extension input from the client extension input.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "[=utf-8 encode=] the client extension input into a CBOR text string."

index.bs Outdated
@@ -2439,20 +2461,23 @@ prompt string, intended for display on a trusted device on the authenticator.
: Extension identifier
:: `txAuthSimple`

: Client argument
: Client extension input
:: A single [=UTF-8 encoded=] string prompt.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the client extension input should be a Javascript type, and Javascript doesn't have UTF-8 strings. It have DOMStrings, which are sequences of 16-bit code units and USVStrings, which are UTF-16.

: Authenticator argument
:: The client argument encoded as a CBOR text string (major type 3).
: Authenticator extension input
:: The client extension input encoded as a CBOR text string (major type 3).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could just be "A CBOR text string" since the client extension processing is in charge of producing it.

index.bs Outdated
:: The authenticator MUST display the prompt to the user before performing either [=user verification=] or [=test of user
presence=]. The authenticator may insert line breaks if needed.

: Authenticator data
: Authenticator extension output
:: A single [=UTF-8 encoded=] string, representing the prompt as displayed (including any eventual line breaks).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a CBOR text string?

index.bs Outdated
:: None, except creating the authenticator extension input from the client extension input.

: Client extension output
:: Returns the authenticator extension output string as JSON string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming this is the algorithm to convert the authenticator extension output into the client extension output, you'll want to mention that it [=utf-8 decodes=] the CBOR into a DOMString.

@equalsJeffH equalsJeffH modified the milestones: WD-05, CR Apr 19, 2017
Copy link
Contributor

@equalsJeffH equalsJeffH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, bikeshed generates linking errors when processing this file. they stem in part from the lines I've commented on below. there's perhaps further ones to address once those are resolved.

I'll review other PRs while these nominal issues are addressed -- i'd like to generate an error-free index.html in order to further review.

Here's what bikeshed says:

> curl https://api.csswg.org/bikeshed/ -F file=@index.bs -F force=1 -F output=err
\033[1;96mWARNING:\033[0m Multiple elements have the same ID 'client-extension-processing'.
Deduping, but this ID may not be stable across revisions.
\033[1;96mWARNING:\033[0m Multiple elements have the same ID 'authenticator-extension-processing'.
Deduping, but this ID may not be stable across revisions.
\033[1;33mLINK ERROR:\033[0m No 'dfn' refs found for 'client processing' that are marked for export.
&lt;a data-link-type="dfn" data-lt="client processing">client processing&lt;/a>
\033[1;33mLINK ERROR:\033[0m No 'dfn' refs found for 'client processing' that are marked for export.
&lt;a data-link-type="dfn" data-lt="client processing" data-link-for-hint="ScopedCredential/[[DiscoverFromExternalSource]](options)">client processing&lt;/a>
\033[1;33mLINK ERROR:\033[0m No 'dfn' refs found for 'authenticator extension output'.
&lt;a data-link-type="dfn" data-lt="authenticator extension output">authenticator extension output&lt;/a>
\033[1;33mLINK ERROR:\033[0m No 'dfn' refs found for 'client extension output'.
&lt;a data-link-type="dfn" data-lt="client extension output">client extension output&lt;/a>
\033[7;32m ✔ \033[0m Successfully generated, with 4 linking errorsLM-SJN-0087

index.bs Outdated

Note: Extensions should aim to define authenticator arguments that are as small as possible. Some authenticators communicate
over low-bandwidth links such as Bluetooth Low-Energy or NFC.


## Extending <dfn>client processing</dfn> ## {#extension-client-processing}
## <dfn>Client extension processing</dfn> ## {#client-extension-processing}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a couple problems with the change in this line:

  1. it removes the dfn for "client processing", thus occurrences of [=client processing=] are dangling, and,
  2. <dfn>Client extension processing</dfn> and {#client-extension-processing} both cause bikeshed to render html elements with ids of "client-extension-processing"

index.bs Outdated

## Extending authenticator processing ## {#extension-authenticator-processing}
## <dfn>Authenticator extension processing</dfn> ## {#authenticator-extension-processing}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar issues in this line as in comment above on L2388

@selfissued
Copy link
Contributor Author

Thanks, Jeff. I've corrected the indexing errors.

Copy link
Contributor

@equalsJeffH equalsJeffH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks MikeJ (@selfissued), this is overall great. I did find some modest things to fix (a couple of which are technical) -- plus I agree with @jyasskin's comments.

index.bs Outdated
1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
1. Otherwise, let |result| be the result of running |extension|'s [=client extension processing=] algorithm on |argument|. If the
algorithm returned an error, return [=a promise rejected with=] either that error or a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a) This algorithm is now synchronous, see the Note: up above in the source.

b) I do not think we can simply say "return that error" (the one returned by running [=client extension processing=]) because who knows what sort of error codes those are and whether they play nice in the browser-guts context in which this alg runs? Perhaps there is some way to return either a "{{TypeError}}" or the extension-generated error packaged-up somehow to differentiate it? OR, perhaps we need to stipulate that all extensions MUST return only DOMExceptions from https://heycam.github.io/webidl/#dfn-error-names-table ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, this is still fundamentally changing how extensions returning errors are handled, see #389 (comment) and #389 (comment).

Is there some way to note the error and [=continue=] with remaining extensions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this aspect of the PR still seems to be generating discussion, I'll plan to remove this part and file it as a separate issue, letting us continue discussing it, while applying the changes in the PR that are non-controversial clear improvements over what's there.

index.bs Outdated
@@ -666,8 +667,9 @@ When this method is invoked, the user agent MUST execute the following algorithm
1. If the {{ScopedCredentialRequestOptions/extensions}} member of |scopedOptions| is [=present=], then [=map/for each=]
|extension| → |argument| of <code>|scopedOptions|.{{ScopedCredentialRequestOptions/extensions}}</code>:
1. If |extension| is not supported by this client platform, then [=continue=].
1. Otherwise, let |result| be the result of running |extension|'s [=client processing=] algorithm on |argument|. If the
algorithm returned an error, [=continue=].
1. Otherwise, let |result| be the result of running |extension|'s [=client extension processing=] algorithm on |argument|. If the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

above comment applies here also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

index.bs Outdated
@@ -1282,8 +1284,8 @@ The [=authenticator data=] structure is a byte array of 37 bytes or more, as fol
<tr>
<td>variable (if present)</td>
<td>
Extension-defined [=authenticator data=]. This is a CBOR [[RFC7049]] map with extension identifiers as keys, and
extension [=authenticator data=] values as values. See [[#extensions]] for details.
Extension-defined [=authenticator data=]. This is a CBOR [[RFC7049]] map with [=extension identifier=] values as keys, and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than [=extension identifier=] values, [=extension identifiers=] may simply magically link (delete "values"), or if not, this will: [=extension identifier|extension identifiers=].

index.bs Outdated
@@ -2269,23 +2273,23 @@ The mechanism for generating scoped credentials, as well as requesting and gener
[[#api]], can be extended to suit particular use cases. Each case is addressed by defining a <dfn>registration extension</dfn>
and/or an <dfn>authentication extension</dfn>. Extensions can define additions to the following steps and data:

- {{CredentialsContainer/create()|navigator.credentials.create()}} request parameters for [=registration extension=].
- {{CredentialsContainer/create()|navigator.credentials.create()}} request and response parameters for [=registration extensions=].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be "request parameters and response values" ?

index.bs Outdated

- {{CredentialsContainer/get()|navigator.credentials.get()}} request parameters for [=authentication extensions=].
- {{CredentialsContainer/get()|navigator.credentials.get()}} request and response parameters for [=authentication extensions=].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

index.bs Outdated
[=authenticatorGetAssertion=] call (for [=authentication extensions=]). These authenticator arguments are passed as name-value
pairs, with the extension identifier as the name, and the corresponding authenticator argument as the value. The authenticator,
in turn, performs additional processing for the extensions that it supports, and augments the [=authenticator data=] as
required by the extension. In addition, the client collects the [=authenticator extension input=] for the above extensions, and passes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, seems we are lacking a definitions for "authenticator extension" and "client extension" -- probably should have them.

index.bs Outdated

- Authenticator processing, and the [=authenticator data=], for [=registration extensions=] and [=authentication extensions=].
- Authenticator extension request parameters, processing, and response parameters for [=registration extensions=] and [=authentication extensions=].

When requesting an assertion for a scoped credential, a [RP] can list a set of extensions to be used, if they are supported by
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this first sentence more properly be:

When creating a [=scoped credential=] or requesting an [=authentication assertion=], a [RP] can list a set of extensions. These extensions will be invoked during the requested operation if they are supported by the client and/or the authenticator.

..?

values in the [=client data=], [=authenticator data=] (in the case of [=authentication extensions=]), or both. Finally, if the
extension requires any authenticator processing, it must also specify an authenticator argument to be sent via the
[=authenticatorGetAssertion=] or [=authenticatorMakeCredential=] call.
A definition of an extension must specify an [=extension identifier=], a [=client extension input=] argument
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/sent/to be sent/ ?

index.bs Outdated
A definition of an extension must specify an [=extension identifier=], a [=client extension input=] argument
sent via the {{CredentialsContainer/get()}} or {{CredentialsContainer/create()}} call,
the [=client extension processing=] rules, and a [=client extension output=] value.
If the extension communicates with the authenticator (meaning it is an [=authentication extension=]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could not an "authenticator extension" be invoked at either or both create() or get() time? i.e., a "registration extension" could involve authenticator processing, no? see also comment above on L2288, as well as the rest of the sentence this comment is on...

index.bs Outdated
be any data that can be encoded in CBOR. An authenticator that processes an [=authentication extension=] that defines such a
value must include it in the [=authenticator data=].
value must include it in the [=authenticator data=] extensions section.
Copy link
Contributor

@equalsJeffH equalsJeffH Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that this sentence..

An authenticator that processes an [=authentication extension=] that defines such a value must include it in the [=authenticator data=] extensions section.

..and this sentence..

As specified in [[#sec-authenticator-data]], the [=authenticator extension input=] value of each processed extension is included in the
-extended data part of the [=authenticator data=].

..are redundant?

Copy link
Contributor

@equalsJeffH equalsJeffH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @selfissued -- this improves extension exposition by orders of magnitude :)

I am fine with merging this now -- LGTM! The only thing I can think of we might want to do (eg for CR milestone) is to delineate the orthongonality of {registration,authentication} extensions from {authenticator,client} extensions in some fashion (may include devising enhanced terminology, i dunno right now) (perhaps an issue to submit...)

@equalsJeffH equalsJeffH merged commit 8eb7b5c into w3c:master Apr 21, 2017
@equalsJeffH
Copy link
Contributor

merged it since we were authz'd to do so on the Wed 19-Apr-2017 webauthn call.

WebAuthnBot pushed a commit that referenced this pull request Apr 21, 2017
index.bs Outdated
@@ -2495,7 +2509,7 @@ error.
:: `appid`

: Client extension input
:: A single [=UTF-8 encoded=] string specifying a FIDO |appId|.
:: A single JSON string specifying a FIDO |appId|.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be nitpicky, since the extension input is a Javascript object, it's a {{DOMString}} rather than a JSON string. JSON is a serialization of many Javascript objects, but it's not the type of things that get passed to web APIs.

No need to fix this before merging, just mentioning it for future patches.

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

Successfully merging this pull request may close these issues.

4 participants