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

providing info about authenticator availability / attachments #764

Closed
subyraman opened this issue Jan 25, 2018 · 8 comments
Closed

providing info about authenticator availability / attachments #764

subyraman opened this issue Jan 25, 2018 · 8 comments

Comments

@subyraman
Copy link

Apologies if some of these usability issues have been answered already. In trying to develop with the spec I'm feeling that it doesn't provide granular information that would be very useful for providing users with an easy authentication workflow. There seems to be no information around:

  • if authenticators are available for registration
  • if those authenticators are enrolled with the relying party

Android, for example, has FingerprintManager for providing this information, with fingerprintManager.isHardwareDetected(), fingerprintManager.hasEnrolledFingerprints(), it has KeyguardManager for determining if a PIN/pattern/password is available, etc.

There are a few usability issues I've run into:

  • User has multiple authenticators on a laptop.
  • During a navigator.credentials.create request, all authenticators are notified and request the user's attention. Windows Hello will pop up a modal, a Yubikey flashes, maybe a soft token pops up a notification as well.
  • The user is confused, and because I can't request a specific authenticator to register, I cannot help guide them through the process.

The spec mentions that relying parties can discover credentials using optional criteria, but I don't know ahead of time what criteria to request.

Another issue:

  1. User registers an authenticator on their laptop.
  2. User attempts to access my website on their phone.
  3. I have to guess if they have a valid authenticator by issuing a navigator.credentials.get request.
  • I can narrow my guess by storing user agent data in my database, or retaining data in the user's browser storage, but this seems fragile.

What would be great is if devs get more granular information about authenticators; their availability, their enrollment status, etc. Something like:

navigator.credentials.isAuthenticatorAvailable() -> Boolean

or more specifically:

navigator.credentials.getAvailableAuthenticatorAttachments() -> AuthenticatorAttachment[]
navigator.credentials.hasEnrolledAuthenticator(credentialID) -> Boolean

Any thoughts around this would be welcomed.

@emlun
Copy link
Member

emlun commented Jan 26, 2018

Thanks for the questions. There are two main reasons for why these pieces of information are not available. First, due to privacy considerations we have chosen to explicitly forbid clients from making it possible for an RP to silently determine what credentials the user owns. Second, the spec is written to support an asynchronous "hot-plugging" interaction flow where the user can plug in authenticator after the RP calls the methods on navigator.credentials.

The privacy considerations are discussed in #184, #204 and #687, and in the editor's draft of the spec in §14.2. Authentication Ceremonies. In summary: providing the information you request would also give malicious RPs a reliable way to silently identify a user without consent.

The "hot-plugging" interaction flow, discussed in #613, #508 and #574, means that the client will wait for an authenticator to become available within a timeout - which could be immediately, e.g., built-in platform authenticators or an already connected USB key - and attempt to use the authenticator when it shows up. If the user denies consent, or ignores the prompt, the client will keep waiting for another authenticator to become available. Only when the timer expires does the client return a failure to the caller. Thus, there is no one instant when the client can check which authenticators are "available", because there could for instance be a USB key "available" sitting next to the computer which would only be seen by the client after the user plugs it in.

The "hot-plugging" flow also ties in with the privacy considerations, as described in §14.2. Authentication Ceremonies.

What you can do is use the isUserVerifyingPlatformAuthenticatorAvailable method to check for the presence of a user-verifying platform authenticator, although that will of course only work for that particular kind of authenticator.

Does this answer some of your questions?

@subyraman
Copy link
Author

@emlun thank you so much for your very detailed answer and all the context around these decisions! This provides a lot to read and I'm still working through it, much appreciated.

I'm somewhat curious what the expected workflow for developers and users would be around the scenarios I asked. I realize that the specification is a draft so it might be difficult to answer, but what should developers do in the situation where a user enrolls a platform authenticator but we don't have the information around what device/platform they are accessing our website from? Is the expected workflow to do some sort of user agent checking/guessing?

@emlun
Copy link
Member

emlun commented Feb 5, 2018

So if I understand you correctly, your main concerns here are:

  1. As a RP, how do I detect if the user has an authenticator they haven't registered with me, so I can ask them if they want to register it?
  2. As a RP, how can I guide the user through the registration process?

Here are my thoughts on (1) in a few scenarios:

  • Scenario 1: The user has an external authenticator.

    In this case there's no way for the browser to know about the authenticator while it's sitting in the user's pocket. On the other hand, since the user has aquired an external authenticator they likely know that they can use it, and is likely to actively seek out a way to register it.

    Another idea is to ask the user if they want to register an external authenticator if they don't have one registered when they register a platform credential (useful as a backup or for "blessing" other platform authenticators, i.e., for the first login on a new client). The RP can tell whether or not a credential belongs to a platform authenticator by using the authenticatorAttachment option when registering the credential, and recording this along with the credential registration.

  • Scenario 2: The user has a platform authenticator, and has no platform authenticator registered with the RP.

    The user may not even be aware that they have a WebAuthn authenticator. It's even possible that a smartphone or laptop could silently become a WebAuthn authenticator in a software update.

    In this case the RP can use the isUserVerifyingPlatformAuthenticatorAvailable method to detect the authenticator. Since the user has no platform authenticator registered, the RP knows this one is not registered and can ask the user if they want to register the authenticator.

  • Scenario 3: The user has a platform authenticator, and already has a platform authenticator registered.

    This is the problematic case, but let's divide it into sub-scenarios depending on how the user logged in. If the user "logged in" automatically via a session cookie or the like, that session ticket could include a flag indicating which of these subscenarios the initial login was in.

    • Subscenario A: The user logged in without using a WebAuthn credential.

      The user may have used some other 2FA method, or doesn't have 2FA enabled.

      In this case, the platform authenticator is likely not registered - otherwise the user would probably have used it.

      Note that this assumes the RP lists all of the user's registered credentials in the allowCredentials option, in which case the user is free to choose to use any that's available and conveient.

    • Subscenario B: The user logged in using an external authenticator.

      Again, the platform authenticator is likely not registered - otherwise the user would probably have used it - so it should be safe to ask. However the user may have actively chosen to not use the platform authenticator for some reason (personal preference, company policy etc), so including a "No, don't ask again" option would probably be welcome.

    • Subscenario C: The user logged in using a platform authenticator.

      In this case, this platform authenticator must already be registered, so there's no need to ask.

I didn't expect this when I started writing the above, but it actually looks like this isn't that big an issue after all! Let me know if I overlooked something in my musings above.

Question (2) is a harder one, I think. Hopefully the browsers will do something to help with this, but what and how is currently outside the spec. If all else fails, I guess you could work around it by asking the user what kind of authenticator(s) they want to use.

What do you think about that?

@emlun
Copy link
Member

emlun commented Feb 5, 2018

Ah, I did indeed miss at least one thing:

Another issue:

  1. User registers an authenticator on their laptop.
  2. User attempts to access my website on their phone.
  3. I have to guess if they have a valid authenticator by issuing a navigator.credentials.get request.
  • I can narrow my guess by storing user agent data in my database, or retaining data in the user's browser storage, but this seems fragile.

This probably does require some guesswork and/or workarounds using cookies or browser storage, I think.

For what it's worth, you can let your guesswork be informed by some timing information. While the API won't let you draw any definite conclusions (again, because of privacy concerns), you could probably guess that if the credentials.get() takes more than, say, 5-10 seconds to complete, the user probably doesn't have a registered platform authenticator on that device. If you then also know the user has no external authenticator registered, you could pop up an option to try another login method (but probably still wait for the credentials.get() to complete - the user could have a physical disability making the process difficult, for example).

@emlun
Copy link
Member

emlun commented Feb 21, 2018

#806 is also related to this. The changes proposed in #809 would allow the RP to detect if the user attempts to re-register an already enrolled authenticator, but only after a user gesture. It would still not support detecting enrolled authenticators before the credentials.create() or .get() call.

@emlun
Copy link
Member

emlun commented Aug 8, 2018

As decided on the 2018-08-08 WG call, we're closing this since there's no way to provide the requested information about the availability of enrolled authenticators without leaking identifying information without user consent. Information about available authenticator attachment modes (but not about credential availability) could possibly be added in L2, but we're closing this for now.

@emlun emlun closed this as completed Aug 8, 2018
@emlun
Copy link
Member

emlun commented Aug 9, 2018

See also #889, #882, #851 which discuss likely future additions that would provide RPs with more information about new credentials. This would for example enable better UX around what kinds of authenticator attachments are possible for a given assertion operation.

@subyraman
Copy link
Author

Thank you for all the responses and for discussing it on your call!

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

No branches or pull requests

4 participants