Analysis of “To use the WebAuthn API, call 'navigator.credentials.create' or 'navigator.credentials.get' within user activated events”-error & user gesture requirements
Vincent
Created: May 14, 2024
Updated: June 19, 2024
Our mission is to make the Internet a safer place, and the new login standard passkeys provides a superior solution to achieve that. That's why we want to help you understand passkeys and its characteristics better.
3.1 Overview of Version and Announcements of Technical Changes
3.2 Current Market Shares of Different iOS Versions (Q1 2024)
In the past, authentication was primarily managed in the backend, largely independent of the browser's implementation standards. However, the introduction of social logins began to shift some of these challenges to the frontend, necessitating the integration of redirects and layers to accommodate the OAuth protocol used to integrate SSO via social logins. The emergence of passkeys has further expanded these frontend responsibilities by the implementation of the WebAuthn standard. This standard, unfortunately, is sometimes interpreted differently across browsers, leading to unique challenges.
In this blog post, we aim to help developers who are navigating the complexities of developing passkey-based applications, especially those experiencing problems with WebAuthn operations on Apple devices using Safari, where you receive `User gesture is not detected. We are going to cover:
What user gesture requirements in Safari are and when they have been introduced / changed: We want to give an overview of the evolution of user gesture requirements and explain what the user gesture errors are about.
How to avoid user gesture errors: We will give our recommendation on how to structure a passkey-login to avoid user gesture errors.
Having encountered and investigated this issue ourselves, we want to share our insights here.
Recent Articles
📖
Chrome Conditional UI: isConditional MediationAvailable() Returns True on Windows 10
♟️
iOS 17: Apple Goes All-In with Passkeys
⚙️
Passkeys Cheat Sheet for Developers
⚙️
Why Passkey Implementation is 100x Harder Than You Think – Misconceptions, Pitfalls and Unknown Unknowns
👤
How to Share Passkeys via AirDrop & Shared Groups on Apple
With iOS 14, iPadOS 14 and Safari 14, Apple introduced Touch ID / Face ID for the web, which for the first time allowed leveraging the local hardware security module (HSM) for the creation of WebAuthn credentials. This was before passkeys were introduced on Apple devices with iOS 16.
To prevent users getting distracting operating system dialogues from pages triggering WebAuthn operations without user consent, Apple implemented a protection that requires the user to have directly triggered the following WebAuthn request. Those actions were called “user activation” and therefore, for WebAuthn calls, were subsequently protected and had “user gesture requirements”. In the first version, there was only a narrow list of use cases that were counted as user gestures:
Become part of our Passkeys Community for updates and support.
JoinThis was a problem for relying parties and websites that had already created flows that would automatically trigger such an operation in a two-factor authentication process. An example can be seen here from AWS today:
Video: AWS Login with automatic WebAuthn Authentication call
After requesting the user identifier (e.g. username / email) and password (first factor), the user is redirected to an intermediate page that would show an animation and at the same time automatically triggers the second factor validation via a WebAuthn call. On Safari 14, this would immediately result in one of those error messages:
To use the WebAuthn API, call 'navigator.credentials.create' or 'navigator.credentials.get' within user activated events
User gesture is not detected. To use the WebAuthn API, call 'navigator.credentials.create' within user activated events.
NotAllowedError: This request has been cancelled by the user.
Large companies suffered at that time under this breaking change (Firefox & Chrome both did not require user gestures prior to WebAuthn operations). Followed by a heated discussions among WebAuthn working group members, there was a prominent patch whitelisting some important Relying Parties (Dropbox, Microsoft, Google, Twitter/X, Facebook):
Taken from: https://github.com/w3c/webauthn/issues/1293#issuecomment-829789071
Although there was some understanding of the reason why this was implemented, the WebAuthn standard was a bit ambiguous about “requiring user gesture”. It was unclear if a user gesture for verification was meant, or if the browser should reasonably make sure that the user actually triggered the action.
Subscribe to our Passkeys Substack for the latest news, insights and strategies.
SubscribeStarting with iOS16, this was addressed and relaxed:
See original Tweet
A “freebie” was introduced, meaning that every website can trigger one `navigator.credentials.get()` call without a user gesture until the next page reload or the next successful WebAuthn operation happen.
Depending on the type of the application and how the page is built, there can be some problems:
Freebie attempt consumed by Conditional UI: The freebie attempt might be consumed by Conditional UI if it is triggered at page load and not when entering the field with an `onClick` event.
User action is not detected as “user gesture”: This can happen within Single Page Applications (SPA) in case the context, where the WebAuthn call is made, is different from the one initiating the user action and therefore destroys the link between the user action / gesture and the following WebAuthn call.
Here is an example of an implementation that triggers the user gesture error on an iOS 16 simulator. Follow these steps to experience the error yourself or watch the video below:
Step 1: Before the video started, the freebie attempt was already consumed by Conditional UI.
Step 2: We switch to a new waiting screen and start the WebAuthn authentication ceremony.
Step 3: Safari immediately interrupts the process with an error
Step 4: We trigger the WebAuthn authentication ceremony by clicking on “Try again”. This time it works (because of the user gesture).
Video: Safari user gesture requirements in action blocking authentication
An important detail here is: This an SPA implemented with React and the specific implementation does change the current page and document structure, therefore destroying the link between the click (user gesture) and the WebAuthn call.
Starting with iOS 17.4 the user gesture requirements were completely lifted and replaced with rate-limiting. Therefore, the problem does not occur anymore. Details about the rate-liming have not been released yet but cause other problems (see Webkit bug we commented on here).
We have prepared a timeline / version history of the releases and current market share of iOS versions, so that the appropriate settings for different operating system versions are easily accessible.
Version | User gesture requirements | Background links |
---|---|---|
< iOS14 | None | Discussion about introduction of user gestures: https://github.com/w3c/webauthn/issues/1293 |
iOS14 | Required for every operation | Release of first version with user gestures: https://webkit.org/blog/11312/meet-face-id-and-touch-id-for-the-web/ |
iOS 14.5 | Whitelisting of important providers | https://bugs.webkit.org/show_bug.cgi?id=220897 |
iOS 16 | One .get() w/o limitation | Twitter confirmation of “Freebie” iOS16 solution: https://bugs.webkit.org/show_bug.cgi?id=220897 |
iOS 17.4+ | User gesture requirements lifted | https://bugs.webkit.org/show_bug.cgi?id=264444 https://forums.developer.apple.com/forums/thread/747036 |
(*) = Versions apply to concurrent iPad/Safari releases (e.g. iOS 14 includes iPadOS 14 & Safari 14)
As of today, iOS 17+ is already installed on most iOS devices (~70-75%), but for now and for the next 12-18 months, a significant share of iOS devices with user gesture requirements will still remain.
What we see within our data and available public statistics depending on the website the following share of iOS Versions is a good approximation as of today:
Version | Share | Release date | User gesture | Passkeys & Conditional UI support |
---|---|---|---|---|
17.4+ | 50% | 2024-03-05 | None | yes |
17.0-17.3 | 25% | 2023-09-18 | One freebie | yes |
16 | 15% | 2022-09-12 | One freebie | yes |
15 | 5% | 2021-09-20 | All | no |
14 | 1% | 2020-09-16 | All | no |
Older | 4% | No | no |
This leaves about 50% of all iOS devices with stricter user gesture requirements that still need to be considered. From
a passkey perspective, only iOS 16 and iOS 17 (versions before 17.4) are of special interest as on those iOS
version isUserVerifyingPlatformAuthenticatorAvailable()
and isConditionalMediationAvailable()
will return true,
because
since iOS 16, passkeys are fully supported by iOS including Conditional UI.
Our approach to this problem is to recommend solutions that allow serving a great UX for all operating systems and versions. In general, there are three options
Our recommendation covers the majority of the problem. However, there are other situations for SPAs where issues might occur, especially with "back navigation" after a passkey operation fails (when navigating back after an aborted passkey authentication the next authentication might fail directly when it is triggered automatically by the back navigation). This is because SPAs never have a "page reload" to reset the freebie counter. Solutions for this issue range from reloading the application to changing flows. Contact us if you need help with your SPA.
In this blog post, we have addressed the complexities of developing passkey-based applications, especially the challenges related to WebAuthn operations on Apple devices using Safari. We covered the evolution of user gesture requirements, how to avoid user gesture errors, and the impacts of different iOS versions on these requirements. To summarize:
User gesture requirements have evolved: Starting with iOS 14, Safari introduced user gesture requirements to prevent unauthorized WebAuthn operations. These requirements have been gradually relaxed and have been removed in iOS 17.4, replaced by rate-limiting.
Solutions vary by implementation: Depending on the type of application and its specific needs, different approaches can be taken to avoid user gesture errors. Options include not implementing Conditional UI, triggering Conditional UI onClick, and combining Conditional UI with an implementation that only triggers WebAuthn after user gestures specified by Apple.
SPAs require special consideration: For single-page applications, issues like "back navigation" after passkey errors/aborts can complicate passkey operations. Solutions may involve reloading the application or changing the flow to reset the freebie counter.
Successfully implementing passkeys requires dedicated know-how and presents with a lot of unknowns. Sharing experiences and solutions can help the developer community overcome these challenges. We invite you to join our passkeys community to discuss these issues and share learnings. Contact us if you need help with your SPA or have any questions about passkey implementation. Let's work together to make passkey authentication a great experience for users.
Table of Contents
Enjoyed this read?
🤝 Join our Passkeys Community
Share passkeys implementation tips and get support to free the world from passwords.
🚀 Subscribe to Substack
Get the latest news, strategies, and insights about passkeys sent straight to your inbox.
We provide UI components, SDKs and guides to help you add passkeys to your app in <1 hour
Start for free
Recent Articles
Enterprise Passkeys: Apple, Google & Microsoft's Offerings
Lukas R. - November 9, 2023
How to Share Passkeys via AirDrop & Shared Groups on Apple
Janina - November 20, 2023