RESOLVED FIXED Bug 213595
[WebAuthn] Use MediaOnly user gesture
https://bugs.webkit.org/show_bug.cgi?id=213595
Summary [WebAuthn] Use MediaOnly user gesture
ynojima
Reported 2020-06-25 05:30:47 PDT
Congratulations for Touch ID/Face ID support! I really appreciate your efforts. I found Safari restricts Touch ID/Face ID usage only within user activated events (Security keys are not restricted). It seems reasonable regulation at first glance, but it also restricts calling WebAuthn within a callback of promise based asynchronous API. Here is a pseudo code that Touch ID/Face ID is not available for registration: ``` someElement.onclick = function(){ var optionsRequest = { // set some parameters }; fetch('http://example.com/webauthn/attestation/options', { method: "POST", body: JSON.stringify(optionsRequest) }) .then(function(response) { var options = generateOptionsFromServerResponse(response); return navigator.credentials.create(options); // WebAuthn is not directly called by user activated event }); } ``` Calling REST API before navigator.credentials.create.get invocation to fetch options parameters like challenge and credentialId(s) are common pattern in many sites (ex. google.com, webauthn.io), and defined practices in FIDO document [1]. What is the objective of this restriction? I assumed it is a guard for unintended Touch ID/Face ID sensor activation, but there is a dialog asking for user consent before activating the sensors. It seems it's a sufficient guard. As far as I know, restricting local authenticators to user activated events are not defined in WebAuthn specification. I suppose the restriction should be removed, or extend the allowed scope to promise callback chain to improve user experience. [1] https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-server-v2.0-rd-20180702.html
Attachments
Patch (2.73 KB, patch)
2020-07-16 21:59 PDT, Jiewen Tan
no flags
ynojima
Comment 1 2020-06-25 16:31:53 PDT
I heard mandating user gesture is not scandalized in W3C WebAuthn spec. https://github.com/w3c/webauthn/issues/1293
Jiewen Tan
Comment 2 2020-06-25 16:35:04 PDT
User activated event is required to use Face ID and Touch ID. This is part of the design of the platform authenticator itself. It has nothing to do with WebAuthn API part.
ynojima
Comment 3 2020-06-25 16:54:16 PDT
I see, but callback of promise chain originally activated by user event should be allowed at least. ( Not sure how hard it is) As stated before, it restricts fetching option data like challenge and credentialId(s) before neavigator.credentials.create/.get call, which is a common pattern in relying party implementations.
bsimic
Comment 4 2020-06-26 12:14:44 PDT
@Jiewan Tan, if this doesn't get fixed, it will essentially make WebAuthn unusable by any relying parties. The user activated event will still be the providing of Touch ID or Face ID. There are zero WebAuthn implementations that currently work using the current implementation because there is a server request required to retrieve the challenge for the options request.
Paul McNamara
Comment 5 2020-06-26 14:10:48 PDT
Likewise it's great to see some real progress with WebAuthn on iOS. I agree with the other posters though - this will break our implementation and likely many others. Would it not make more sense to simply have a native consent UI when "platform" is requested? Confirmation of this would meet the user activated requirement would it not? If the goal is to prevent nuisance popup UIs then it's currently inconsistent as you still get one if create/get are not called from within a user-activated event handler. No other browser implementations (including OSX Safari using the touchbar) work this way to my knowledge.
Bart de Water
Comment 6 2020-06-29 11:57:00 PDT
This really confused me as well. I tried Shopify, GitHub and https://github.com/cedarcode/webauthn-rails-demo-app and none of them prompted me to use TouchID as I expected after upgrading to iPadOS 14. Only https://webauthn.me/debugger works as expected because it's a demo using client-side generated challenges.
Radar WebKit Bug Importer
Comment 7 2020-06-30 11:02:31 PDT
Jiewen Tan
Comment 8 2020-07-01 17:01:13 PDT
Hi Developers, Removing the user gesture requirement unfortunately is not an option. The benefit of it is probably not obvious at the current stage. However as you could have imagined, the UI could evolve into a more streamlined version in the future that will certainly be beneficial by this hard requirement. At the same time, we are considering improvement over the user gesture mechanism, like things in User Activation API that could let the user gesture bit being carried through the promise chain. However, such thing doesn't exist in WebKit yet. Implementing such improvement will take quite some time, and the improvement will probably not be shipped soon. Therefore, I suggest you could prefetch the nonce before the user action as a solution for now.
Fat Bloke
Comment 9 2020-07-06 02:44:22 PDT
Just adding my disappointment to this thread. This approach breaks our implementation too. This will be perceived as Apple going their own way and perverting open standards as they did with the recent OpenId Connect/Sign in with Apple debacle. https://openid.net/2019/06/27/open-letter-from-the-openid-foundation-to-apple-regarding-sign-in-with-apple/ Please Apple, review this restriction.
Alex
Comment 10 2020-07-07 15:17:42 PDT
I also would like to express my disappointment in this decision. By requiring websites to update their ordering of REST calls leaves a poor user experience when they wonder why they can login into one website with WebAuthn, but not in another, when in reality it should work with both websites. Why is it not possible to show a consistent dialog, such as Apple Pay which requires user consent to trigger authentication by a new fingerprint touch or double tap to activate Face ID scan and preserve existing behavior?
Jiewen Tan
Comment 11 2020-07-16 21:59:56 PDT
Brent Fulgham
Comment 12 2020-07-17 10:58:45 PDT
Comment on attachment 404536 [details] Patch r=me
Brent Fulgham
Comment 13 2020-07-17 11:00:08 PDT
For those following along on this radar, we have revised the handling of user gesture to follow the model of our media gesture requirements. This should resolve many of the concerns raised in this thread. It is helpful to have specific examples of cases where you find the user gesture to be a problem so we can review and see if we can find a path forward that complies with the requirements of our Local Authentication features on our devices.
Alex
Comment 14 2020-07-17 11:13:41 PDT
https://webauthn.io/ is a good website to test with where this bug is triggered. You can also create a free Okta tenant at https://developer.okta.com and test there as well.
Jiewen Tan
Comment 15 2020-07-17 12:15:44 PDT
This patch should have resolved issues with XHR, but not Fetch API. Bug 214444 is tracking the progress of Fetch API.
Jiewen Tan
Comment 16 2020-07-17 12:16:34 PDT
Comment on attachment 404536 [details] Patch Thanks Brent for r+ this patch.
EWS
Comment 17 2020-07-17 12:30:28 PDT
Committed r264528: <https://trac.webkit.org/changeset/264528> All reviewed patches have been landed. Closing bug and clearing flags on attachment 404536 [details].
Jiewen Tan
Comment 18 2020-07-17 16:41:30 PDT
(In reply to Alex from comment #14) > https://webauthn.io/ is a good website to test with where this bug is > triggered. > You can also create a free Okta tenant at https://developer.okta.com and > test there as well. Confirmed this fix works for the first website. For the second one, it's not obvious for me where I could register the platform authenticator.
Alex
Comment 19 2020-07-17 17:27:20 PDT
Honestly if it works with that website you should be good to go, but here is how you would enable it on Okta. Login to your developer okta tenant with username & password. If you see Developer Console in the top left of the page, click it and select Classic UI to switch. Then under Security --> MultiFactor you can enable WebAuthn as available for your tenant. Afterwards, leave the Okta admin portal and go back to the user profile page. You'll be able to enroll the factor there.
vganesh
Comment 20 2020-07-18 11:01:56 PDT
Which iOS release would this be available in? Will it be in beta3?
Billy Lo
Comment 21 2020-10-05 09:17:40 PDT
(In reply to Jiewen Tan from comment #18) > (In reply to Alex from comment #14) > > https://webauthn.io/ is a good website to test with where this bug is > > triggered. > > You can also create a free Okta tenant at https://developer.okta.com and > > test there as well. > > Confirmed this fix works for the first website. For the second one, it's not > obvious for me where I could register the platform authenticator. Hi, Jiewen: which iOS/Safari version did you use for verification? Would like to replicate it for our site too. thx.
Jiewen Tan
Comment 22 2020-10-05 10:56:38 PDT
(In reply to Billy Lo from comment #21) > (In reply to Jiewen Tan from comment #18) > > (In reply to Alex from comment #14) > > > https://webauthn.io/ is a good website to test with where this bug is > > > triggered. > > > You can also create a free Okta tenant at https://developer.okta.com and > > > test there as well. > > > > Confirmed this fix works for the first website. For the second one, it's not > > obvious for me where I could register the platform authenticator. > > Hi, Jiewen: which iOS/Safari version did you use for verification? Would > like to replicate it for our site too. thx. iOS 14 and macOS Big Sur beta.
Aric
Comment 23 2020-10-25 09:03:35 PDT
Version 14.0 (14610.1.28.1.10) 10.14.6 (18G6032) MacBook Pro (15-inch, 2019) As far as I can tell this issue remains. Safari always prompts for security key, never Touch ID. Sites tested: webauthn.me webauthn.io
Jiewen Tan
Comment 24 2020-10-26 13:35:45 PDT
(In reply to Aric from comment #23) > Version 14.0 (14610.1.28.1.10) > 10.14.6 (18G6032) > MacBook Pro (15-inch, 2019) > > As far as I can tell this issue remains. > Safari always prompts for security key, never Touch ID. > > Sites tested: > webauthn.me > webauthn.io Do you check isUVPAA? Touch ID won't work on any macOS before Big Sur.
Michael
Comment 25 2020-11-03 14:13:47 PST
Hi Jiewen Tan, we've noticed a couple of things: 1) TouchID prompt is not seen when WebAuthn API is invoked as a result of event trigger. e.g. Button is clicked + API call is made to backend to get challenge and on success we trigger an event. Then, event listener calls credentials.create. Can we fix this? 2) Today, to avoid many clicks we programatically trigger credentials.get as soon as user lands on the WebAuthn screen in login flow. Chrome allows it on MacOS and doesn't filter TouchID. Is Safari going to fix this to have the same behavior, or do we need to have an explicit click from the user triggering the WebAuthn prompt? Just trying to understand what the direction is, and the degree of user interaction required. Thank you very much for your time and help!
Jiewen Tan
Comment 26 2020-11-03 14:49:23 PST
(In reply to Michael from comment #25) > Hi Jiewen Tan, we've noticed a couple of things: > > 1) TouchID prompt is not seen when WebAuthn API is invoked as a result of > event trigger. > e.g. Button is clicked + API call is made to backend to get challenge and on > success we trigger an event. > Then, event listener calls credentials.create. > Can we fix this? Can you be more specific? Can you file another bug and upload your test case? > 2) Today, to avoid many clicks we programatically trigger credentials.get as > soon as user lands on the WebAuthn screen in login flow. Chrome allows it on > MacOS and doesn't filter TouchID. Is Safari going to fix this to have the > same behavior, or do we need to have an explicit click from the user > triggering the WebAuthn prompt? Just trying to understand what the direction > is, and the degree of user interaction required. For us, it's going to require user interactions. > > Thank you very much for your time and help!
Michael
Comment 27 2020-11-04 15:03:14 PST
Hi Jiewan, thanks for your quick reply. Understood on the user interaction requirement. We can create a separate issue later with a js fiddle or similar example implementation to illustrate the callback issue.
Levon Karapetyan
Comment 28 2020-11-09 03:35:07 PST
Hi, I have noticed that when the geolocation API is used between user click and WebAuthn call, then Safari on iOS 14 restricts Touch ID/Face ID usage. I'd like to know whether this is also a bug or the expected behavior. Here is a code example: document.getElementById("mybutton").onclick = function() { navigator.geolocation.getCurrentPosition(register, register); } function register() { var options = {...}; navigator.credentials.create({ publicKey: options }) .then(console.log) .catch(console.error); }
Jiewen Tan
Comment 29 2020-11-09 11:54:14 PST
(In reply to Levon Karapetyan from comment #28) > Hi, > > I have noticed that when the geolocation API is used between user click and > WebAuthn call, then Safari on iOS 14 restricts Touch ID/Face ID usage. I'd > like to know whether this is also a bug or the expected behavior. > > Here is a code example: > document.getElementById("mybutton").onclick = function() { > navigator.geolocation.getCurrentPosition(register, register); > } > > function register() { > var options = {...}; > navigator.credentials.create({ > publicKey: options > }) > .then(console.log) > .catch(console.error); > } That's expected behavior. However, I will encourage you to file a bug and cc me.
Aric
Comment 30 2020-11-13 11:32:09 PST
(In reply to Jiewen Tan from comment #24) > (In reply to Aric from comment #23) > > Version 14.0 (14610.1.28.1.10) > > 10.14.6 (18G6032) > > MacBook Pro (15-inch, 2019) > > > > As far as I can tell this issue remains. > > Safari always prompts for security key, never Touch ID. > > > > Sites tested: > > webauthn.me > > webauthn.io > > Do you check isUVPAA? Touch ID won't work on any macOS before Big Sur. Touch ID works fine on these same sites with Mojave+ and Chrome. The published updates indicated this would work in Safari 14, and Safari 14 is now available on Mojave. Can you point me to the documentation that says you must have Big Sur to make this work?
Jiewen Tan
Comment 31 2020-11-13 12:49:42 PST
(In reply to Aric from comment #30) > (In reply to Jiewen Tan from comment #24) > > (In reply to Aric from comment #23) > > > Version 14.0 (14610.1.28.1.10) > > > 10.14.6 (18G6032) > > > MacBook Pro (15-inch, 2019) > > > > > > As far as I can tell this issue remains. > > > Safari always prompts for security key, never Touch ID. > > > > > > Sites tested: > > > webauthn.me > > > webauthn.io > > > > Do you check isUVPAA? Touch ID won't work on any macOS before Big Sur. > > Touch ID works fine on these same sites with Mojave+ and Chrome. The > published updates indicated this would work in Safari 14, and Safari 14 is > now available on Mojave. Can you point me to the documentation that says you > must have Big Sur to make this work? https://webkit.org/blog/11312/meet-face-id-and-touch-id-for-the-web/
Teodor
Comment 32 2020-12-13 16:49:14 PST
I think there is another common use-case that was missed. When using WebAuthn as a second factor during authentication, combined with Safari's credential autofill, we get into a situation where the user is automatically trapped by Safari into a failed authentication with application code having very little control. User opens the login page in Safari, they see the auto-login/autofill card appear on the bottom of the screen. They click on their email address there, which causes the <form> to be automatically submitted. The code that handles form submit then sends a fetch() request that resolves with options for credentials.get call. At this point, it is indistinguishable between form having been submitted via Enter key press, or auto-submitted by auto-fill. So calling credentials.get at this point results in a confusing prompt about inserting the security key, while the user is expecting FaceID to activate. Yes, hacks can be applied to detect keypresses in form fields, among others. But I think that the correct solution is to treat the user-activated autofill of credentials as a user gesture.
Teodor
Comment 33 2020-12-15 09:26:47 PST
Furthermore, ASWebAuthenticationSession should be exempt from the user gesture requirement. Any native app that relies on web-based authentication (either first- or third-party) that in turn may use WebAuthn, should be trusted in the same manner that calling LAContext with enrolled Face ID results in an immediate scan. I do think that this issue is not resolved, as expected authentication flows are still not working. But if you think that I should file a separate bug report, let me know.
Jiewen Tan
Comment 34 2020-12-15 11:21:59 PST
(In reply to Teodor from comment #32) > I think there is another common use-case that was missed. > > When using WebAuthn as a second factor during authentication, combined with > Safari's credential autofill, we get into a situation where the user is > automatically trapped by Safari into a failed authentication with > application code having very little control. > > User opens the login page in Safari, they see the auto-login/autofill card > appear on the bottom of the screen. They click on their email address there, > which causes the <form> to be automatically submitted. The code that handles > form submit then sends a fetch() request that resolves with options for > credentials.get call. At this point, it is indistinguishable between form > having been submitted via Enter key press, or auto-submitted by auto-fill. > So calling credentials.get at this point results in a confusing prompt about > inserting the security key, while the user is expecting FaceID to activate. > > Yes, hacks can be applied to detect keypresses in form fields, among others. > But I think that the correct solution is to treat the user-activated > autofill of credentials as a user gesture. Thanks for your feedback. Can you file a separate bug on this?
David Earl
Comment 35 2021-02-04 11:13:37 PST
I have been trying this on my test example (at https://webauthn.savesnine.info ) on iPad OS 14.4 and on iOS 14.4, in response to a user bug report re the code that implements that example, that webauthn with iPhone fingerprint had stopped working. It works for me - in the example. But it fails in the same way as the bug they submitted in a real world app. The difference is they are in Japan and I am in the UK, only a few km from my server. Their server round trip (and also the server response in a real app) is significantly longer than me using the example. I tried adding a setTimeout so the workflow becomes click - fetch credentials/challenge - receive them in callabck - wait for setTimeout callback - ask for authentication in setTimeout callback This still works for me in the example case for timeouts below 700ms. At 800ms it fails. It looks to me like there is a timer after the last user interaction during which the authentication request is allowed (probably 1s - my 800ms artificial delay + server roundtrip, seems plausible). My Japanese correspondent has a much longer round trip time (and you may or may not also if you try the example). I am not clear from the discussion here what release version of iOS this is fixed in, and whether that time delay IS the fix or is what it was before the fix this bug refers to and the real fix hasn't got into a public release yet. If 14.4 should work, then it doesn't, at least not when there is a sufficient delay between pressing the button and asking for authentication. When it works for me (short roundtrip) I get one iOS box pop up which asks which method I'd like to use, I reply fingerprint, and then I get the fingerprint prompt. When it fails, I just get an invitation to plug in my security key. The only difference is the length of time it takes to ask the server for the challenge/credentials.
Note You need to log in before you can comment on or make changes to this bug.