-
Notifications
You must be signed in to change notification settings - Fork 72
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
Replace the 60 second timeout with a random delay #453
Conversation
also cc @martinthomson, @bvandersloot-mozilla and @cboozar |
FWIW Christian and I chatted about this and I think the principle here should be that zero-account failures should be indistinguishable from a user not interacting with the UI. |
spec/index.bs
Outdated
@@ -484,6 +475,11 @@ failure. | |||
1. If |config| is failure, return failure. | |||
1. Let |accountsList| be the result of [=fetch the accounts list=] with |config|, |provider|, | |||
and |globalObject|. | |||
1. If |accountsList|'s size is 0 or if the fetch threw an exception: | |||
1. Stop processing the algorithm and wait indefinitely. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One issue I see with this is that we do not allow new FedCM calls when there is a pending call. So this effectively means that the FedCM API cannot be invoked again in this page load. Other than that, this might be ok though it seems to require an implementation change on the Chromium side, right? Also, would we need to note somewhere that this would also be the behavior when the user closes/dismisses the user agent UI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, and IMHO one that gets at the heart of why I think it's good to move the spec in this direction. Imagine an implementation which chooses to suppress or show very quiet UI when FedCM is invoked without a user gesture, but will show noisier UI when invoked in response to eg. a "login with X" button click. Such an implementation needs a way to cancel the first request and show the second (possibly with <60 seconds between them), right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do have a way to cancel the UI: https://w3c.github.io/webappsec-credential-management/#dom-credentialrequestoptions-signal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, of course. So is it OK to leave aborting current requests up to the page, or should we auto-abort when a new request comes in? In particular, thinking about multi-IDP scenarios with two un-cooperating SDKs on the same page. Presumably the one with a user gesture should take priority over one without (regardless of whether it's before or after), right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question, hmm
Currently the spec requires us to fail with NotAllowedErr (step 5 in https://w3c.github.io/webappsec-credential-management/#algorithm-store) and payments also fails a second request if the first one is not done yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for the hypothetical scenario where the page uses a FedCM call during the page load and then there is a click which triggers another FedCM call, we would have two options:
- Remove the UI from the first FedCM call (possibly reject the promise, or just leave it unresolved) and initiate the second call. This has the advantage that there is no need to manually abort the first FedCM call.
- Force the developer to abort the first FedCM call manually, otherwise reject the second call (this is the current behavior). This has the advantage that we don't have to guess which FedCM calls should take priority, but does seem to require a bit more work from the RP. It also assumes the IDP does provide an abort method to cancel the call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the PR to not have the indefinite timeout. Please take another look. Also interested in thoughts from others (@martinthomson / @cboozar ?)
spec/index.bs
Outdated
@@ -484,6 +475,11 @@ failure. | |||
1. If |config| is failure, return failure. | |||
1. Let |accountsList| be the result of [=fetch the accounts list=] with |config|, |provider|, | |||
and |globalObject|. | |||
1. If |accountsList|'s size is 0 or if the fetch threw an exception: | |||
1. Stop processing the algorithm and wait indefinitely. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for the hypothetical scenario where the page uses a FedCM call during the page load and then there is a click which triggers another FedCM call, we would have two options:
- Remove the UI from the first FedCM call (possibly reject the promise, or just leave it unresolved) and initiate the second call. This has the advantage that there is no need to manually abort the first FedCM call.
- Force the developer to abort the first FedCM call manually, otherwise reject the second call (this is the current behavior). This has the advantage that we don't have to guess which FedCM calls should take priority, but does seem to require a bit more work from the RP. It also assumes the IDP does provide an abort method to cancel the call.
As-is, the spec does not correctly handle fetch errors; this change ensures that we correctly turn them into exceptions. I am keeping the name of the processResponseConsumeBody parameter even though it is no longer directly passed to the fetch algorithm because conceptually this is a wrapper around fetch and the parameter does have the same meaning as in the fetch algorithm. This was split out of PR w3c-fedid#453
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am splitting the relatively uncontroversial change to the fetch error handling into PR #455 so that this PR can focus on the timeout handling.
I will also update this PR to what Chrome currently implements which should be less controversial than this PR's current proposal.
The extract and convert steps can throw exceptions, but fetch's processResponseConsumeBody does not really handle that. Instead, set the respective return objects to failure and update the call site where necessary. This was split out of PR w3c-fedid#453 with major modifications.
The extract and convert steps can throw exceptions, but fetch's processResponseConsumeBody does not really handle that. Instead, set the respective return objects to failure and update the call site where necessary. This was split out of PR w3c-fedid#453 with major modifications.
* Correctly handle fetch errors The extract and convert steps can throw exceptions, but fetch's processResponseConsumeBody does not really handle that. Instead, set the respective return objects to failure and update the call site where necessary. This was split out of PR #453 with major modifications. * review comments
This is a better user experience and also gives user agents mores flexibility for their UI. It also makes the spec match Chrome's current implementation. This change does not add a delay when the user closes the dialog explicitly. This is not necessary because the timing is effectively random and therefore indistinguishable from other failures that do have this delay, and it allows RPs to fall back to different types of authentication immediately in this case. Closes w3c-fedid#389
Please take another look! |
spec/index.bs
Outdated
1. Let |throwImmediately| be the value of the second element of the pair. | ||
1. [=Queue a global task=] on the [=DOM manipulation task source=] | ||
to throw a new "{{NetworkError}}" {{DOMException}}. If |throwImmediately| is true, this | ||
MUST happen after a random delay between 0 and 60 seconds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of comments:
- I think it is a bit clearer to add the wait before the queue a global task step, otherwise. this sounds like this delay could happen in main thread! Something like
1. If |throwImmediately| is true, wait ... 1. Queue a global task
- Do we need to hardcode the 60 seconds here? In fact, does the delay here need to be mandatory? I can imagine user agent UI such that it only attempts fetching once the user has interacted enough with the dialog, and may thus not need this delay. Perhaps making this wait optional and explaining the purpose is a better approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, but let me know if you want this less prescriptive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! We should get someone from Mozilla to take a look before merging though...
@martinthomson, @bvandersloot-mozilla and @cboozar -- I'd love to hear your thoughts on this PR |
Sorry for the late reply, these changes look good to me 👍 |
Thanks for the review! Merging. |
SHA: c8609ec Reason: push, by npm1 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This is a better user experience and also gives user agents mores
flexibility for their UI. It also makes the spec match Chrome's current
implementation.
This change does not add a delay when the user closes the dialog
explicitly. This is not necessary because the timing is effectively
random and therefore indistinguishable from other failures that do
have this delay, and it allows RPs to fall back to different types
of authentication immediately in this case.
Closes #389
Preview | Diff