-
Notifications
You must be signed in to change notification settings - Fork 19
These are some ideas and concepts we need to convey in the UI. Writing these out fully to make it clear. I will update as I come up with more, and maybe do some paper wireframes and add screenshots from other OS implementations.
Entrypoints
There are two main entrypoints: browsers and apps. Browsers and apps have different permissions prompts, but the UI for the authentication ceremony should be the same
Intro screen
Maybe the first time a user uses the credential portal, they should be introduced to it. Or maybe just for passkeys since they're new? Or maybe we just let the normal UI guide them.
e.g.
- "This is GNOME Credentials, here's what you can do," or
- "This is what a passkey is, click to continue"
UI modes
- Standard: a modal over the window of the app that called it.
- Ambient: a non-intrusive window (e.g. a notification) that can be activated by the user. This is useful for browsers if they want to sign in users if they have credentials, but otherwise let them keep browsing
Permissions
Cf. #184
This section is sort of out of scope of this particular project, since it involves the UX of various app distributors, but still good to get an idea of how we want to do this so we can all agree.
Permissions are based on web origins (think domain, like example.com). An application/browser can have different levels of permission per origin.
- privileged: no explicit permission prompt for the origin
- unprivileged: requires an explicit permission prompt for the origin
These privilege levels can be scoped to a particular origin or global (any origin).
Only browsers should be granted global, privileged access to credentials. They should be prompted the first time they try to use any origin with "ExampleBrowser wants to access credentials for all websites." This permission should also be clearly displayed before installing the app, but that's up to app distributors.
Other combinations are allowed:
- an app may be granted privileged, scoped access to its corresponding web origin(s), e.g., a Spotify app could be given privileged permissions to
spotify.comto skip prompts. - an app may be granted unprivileged, global access, for example, for an app that allows configuring self-hosted software. "FooApp wants to access foo.self-hosted.home". This will be prompted separately for each domain.
- an app may be granted unprivileged, scoped access to an origin. This is useful if the developer of a third-party app does not have the appropriate access to associate the origin with their app: they may have the user's machine prompt them "ThirdPartyApp wants to access credentials for acme.com"
These can also be mixed, e.g. if FooApp has a flagship instance of the service at fooapp.com, they could be given privileged, scoped access to that origin, but unprivileged, global
(On a technical note, these permissions are requested by the app developer via entitlements, and should be checked by the app distributors whether it is valid, which should help that last category of unprivileged, scoped access from becoming an unmitigated phishing vector.)
Permission persistence
Do we want to have the ability to grant permissions scoped by time? I.e., This time, Always, Not this time, Never?
Runtime vs. install time permission prompts
We need to decide whether prompting at runtime is necessary or just at install time. I lean toward being more explicit in this case and doing it both install time and runtime, since it might be a gap of time before they request credentials after installing.
Managing Permissions
We probably should have a way to list the origin permissions for each app. Does this belong in GNOME Settings?
Credential Selection
The credential selection screen should make a few things clear:
- whether a credential is being created or asserted/used
- the origin of the request (app ID, or browser + website domain), requested credential domain (e.g. WebAuthn RP ID for passkeys, or just a "service identifier" for passwords, etc.)
- if the request is "cross-origin", then notify the user "somehow".
- an app using the global, unscoped permission can be considered cross origin, but there are only two IDs involved, the App ID and the requested origin.
- A browser request can be considered cross-origin when it reports the "top origin" to be different than the request origin, e.g. if the request is coming from a
bank.comiframe on amerchant.comwebpage. In this case, there are two origins plus the browser that should be displayed.
- the credentials that are available for the request
- other credentials that don't match explicitly, but may nonetheless be applicable (e.g. if a password request for example.co.uk comes in, but the user has a credential example.com stored, but it's the same relying party using a different domains for different regions). This does not apply to passkeys, since origin binding is required.
The credentials available can be split along a few dimensions:
- credential types
- known vs. known
- device/authenticator transport
"Known" vs. "Potential" Credential sources
Some credentials are known to match the incoming request as soon as it starts. This includes:
- passkeys stored in the platform authenticator
- passkeys and passwords stored in a password manager that has pushed credential metadata to credentialsd
- linked CTAP2 hybrid devices (e.g. a smartphone that you have previously connected to this computer and opted to save a connection to)
- A plugged in USB authenticator with a CTAP2 PPUAT (essentially, a token with permission to view credential metadata on the USB device)
Potential credentials are all the other types of credentials that are not known to the service at request time, like
- USB (without that token support mentioned above), NFC, BLE authenticators
- credentials on other devices, accessed via CTAP2 hybrid QR code
- locked credential provider
The "known" credentials should probably be prioritized over the "potential" credentials. Some of the potential credentials require a click (like the locked credential provider), but others may be activated by the user in other ways to advance the ceremony (e.g. scanning the QR code, touching the USB key, tapping the NFC credential).
Credential Types
We intend to allow apps to request multiple credential types for logging in, like passkeys, passwords. (On creation, only one credential type is allowed.)
When apps request multiple credentials to authenticate with, we'll need to distinguish the type of request (and probably prioritize passkeys over passwords)
Credential transports
USB
When a USB credential is plugged in, it becomes immediately available as a credential source. The physical device itself begins blinking, and the user can touch it to select this credential.
One UI quirk that different desktop platforms do differently is around what to do when multiple USB credentials are plugged in. macOS requires you to touch the USB device (to select), enter the PIN, and then touch again to assert user presence. Windows skips the first touch and allows you to click on the USB device, skipping straight to PIN entry, and then one touch for user presence. (I think they may also automatically advance to the USB screen when it is plugged in and there is only one available.)
(The platform may also have a PPUAT that allows it to query the available credentials. Should we update the list of known credentials when this happens?)
- If the user plugs in their USB device, should we immediately switch to it, or should we still require a touch?
Assuming we're going with "touch to select," here's a general flow:
- User plugs in device (or it was already plugged)
- User touches device to select it.
- Potentially, the authenticator transitions to requesting built-in UV (basically fingerprint on all known devices)
- The user UV attempt may fail (wrong finger, not quite right, device glitch). Atte
- attempts left means total attempts left until the authenticator will no longer allow fingerprint auth, and the user must use a PIN. It doesn't mean authenticator reset, like on the PIN step below.
- It also is global (e.g. lasts between power cycles, and there may be an internal per-power cycle limit that is not given to us)
- Step 1 may repeat, decrementing attempts left.
- The authenticator may decide to short-circuit the attempts left and jump to PIN auth.
- this is unfortunate, since the user can become confused if there are 3 attempts left, but it jumps to PIN auth. Maybe we shouldn't show the number explicitly here.
- The user UV attempt may fail (wrong finger, not quite right, device glitch). Atte
- Authenticator transitions to requesting PIN. UI shows PIN entry dialog
- This may be skipped if no PIN is set up and user verification is not required by the RP.
- This may also be skipped if a fingerprint was used for user verification.
- Potentially, the user enters the wrong PIN. UI shows how many attempts left before total reset of the device occurs.
- We should probably also make the user unplug and replug the device after a few attempts to slow them down from burning up all their attempts and perhaps remind them that they're using a different authenticator than they're expecting.
- we should probably deduplicate PIN attempts and let the user know "you already tried that one" (technical point, we shouldn't store the actual PIN, just a cryptographic hash suitable for passwords of the PIN for comparison"
- if we do that, I don't know whether we should store the PIN hash between power cycles
- The user enters the correct PIN
Hybrid QR Code
- The UI displays the hybrid QR code
- we need to decide whether to always do this, or to require a click.
- there may be some concern about shoulder surfing the QR code, but I'm not sure that's a wide enough concern to warrant hiding it by default.
- User scans QR code. UI transitions to showing a "Connecting" state, giving instructions that the
- This requires Bluetooth to be enabled on both devices. We probably will automatically enable Bluetooth for the user. (Maybe if Bluetooth is not enabled on the laptop, we would hide the QR code and require an explicit click to start the flow, with implicit consent to start Bluetooth) The user might need to be instructed to enable Bluetooth on their other device.
- Android is going to start skipping the prompt to enable Bluetooth and just do it automatically when the QR code is scanned, and I think currently both Android and iOS prompt the user to enable Bluetooth if they scan and it's turned off. So this might be a responsibility of the mobile device platform, not ours. But other UIs, like Chrome, instruct the user to "keep the devices close together and have Bluetooth enabled."
- User's device finishes connecting. UI transitions to showing a "Connected" state.
- The user should be instructed to "follow the instructions on the mobile device"
- Potentially, the user quits or there is a connection error
- Return an authenticator error back to the UI
- User selects credentials on their mobile device, and the credential is sent back to the laptop
- ? User is prompted to store this device for later
- As mentioned elsewhere, maybe this could be a notification that the user clicks since it's sort of out of band of the ceremony they're trying to accomplish
- UI completes, credential is returned to calling application.
Credential Provider
If the user selects one of these, the credential provider will be notified to unlock the vault (if necessary) and collect user verification. The credential provider may defer to something like Polkit for user verification, which would mean that their app's window is never drawn, so they can go straight from clicking on the credential, to authenticating with Polkit, and back to the calling application with the successful credential.
TODO: expand on this
Linked Device
- User clicks on linked device, transitions to "Connecting" state
- User's mobile device gets a notification
- Potentially, the user denies
- Return an authenticator error back to the platform
- The user accepts, UI transitions to Connected.
- The following steps are the same as hybrid QR code flow above, with the omission of the device linked, since this one is linked already.
- Potentially, the user quits or there is a connection error
- Return an authenticator error back to the UI
- User selects credentials on their mobile device, and the credential is sent back to the laptop
- UI completes, credential is returned to calling application.
Platform authenticator
- if we do device-bound credentials, we should call out that they are not backed up, and the user should register multiple authenticators if the website allows it.
- maybe this could be a low-priority notification sent after the assertion, if we detect that there are no other credentials (
excludeCredentialsis empty on the WebAuthn registration request) - We could also use WebAuthn signals on assertion, if
signalAllAcceptedCredentialssays that the only credential is the device-bound credential we just used, we could send a warning notification.
- maybe this could be a low-priority notification sent after the assertion, if we detect that there are no other credentials (
NFC
TODO
BLE
TODO
Other sorting
- Should we sort by last used credential per origin? Or just by longest matching origin, and then alphabetically by username? Or maybe both (promote last used credential on top, and then do origin/username sorting. I think Windows Hello does this)
- Apps have the ability to influence the portal UI via hints, e.g. if they know their user's credential is a security key, they can pass
security-keyas a hint so that we should show the security key option prominently so the user isn't confused. These are just hints, so we shouldn't remove the other options, only prioritize the hinted ones.
Other screens
These may or may not belong inline in the ceremony flow.
- Setting up a PIN on the selected CTAP2 authenticator if the RP requires UV and it is not set
- Setting up built-in UV, e.g. enroll fingerprint onto the device
- Linking a hybrid device, post ceremony
- Maybe a notification they can click to store the connection to the device?
- Multiple credentials: sometimes a selected CTAP2 authenticator returns multiple matching credentials after doing user verification and user presence. One needs to be selected by the user. (Mostly applicable for physical keys, like USB, NFC, BLE)
- Sidenote: Users should probably be able to travel back and forth between different authenticators during the ceremony. E.g., if they try a USB credential, but it says there are none matching, they should be able to go back and try a different USB authenticator, without going all the way back to the app and retrying.
- Errors:
- No matching credentials found on this authenticator
- Matching credential already exists (on creation), don't need to create another one
- general authenticator error
- PIN not set
All reactions
Replies: 2 comments 2 replies
Intro screen
I never think help shown on the first time only is that user friendly, especially for programs/concepts that are triggered by other events and thus show up unexpectedly.
It is all too easy to close that first screen, maybe because the modal was unexpected, or it was triggered accidentally, and then when the user comes to use it for the first time for real there is nothing displayed. Similarly a user may not remember the relevant details later. In the extreme case the user may not even be the same person who triggered the modal the first time, such as for a shared computer.
From a maintainability perspective it also introduces a code path that is not exercised in regular use.
My suggestion would be to either make such information a permanent part of the UI, perhaps being fairly short with links to more information. Another approach might be to have the information be collapsible and then remember the state of that collapse, though that does require retaining additional state.
UI modes
Does ambient mode need any kind of UI for the system component? Isn't it just a background check against "known" credential sources, and the browser handles all the UI?
Permission persistence
I'm of two minds on the "Never" option. On the one hand it is a useful defence against buggy apps that accidentally keep requesting permissions they don't need, and there can even be a security argument as a defence against an MFA fatigue style attack where an application repeatedly requests credentials in the hope that the user accepts the prompt to make it stop annoying them.
On the other hand I could see a user dismissing a prompt with "Never" if they want to stop it blocking their current task, and then being confused about why it isn't working later when they do want to sign in. This behaviour has been trained into users with all the cookie banners and newsletter popups that modern digital surfaces are infected with. It is commonly quite difficult to undo selecting "Never", as it often requires diving deep into uncommon settings menus.
Managing Permissions
There are permissions listed on the GNOME Settings page under Apps > AppName. So I imagine that could be expanded to include credential permissions. The other way to pivot it would be to have a list of credentials and see what apps can access them, which would have to be a new section, or perhaps a separate app.
Runtime vs. install time permission prompts
Getting permissions at runtime is a lot nicer for systems that install things non-interactively. For example, maybe an update running in the background adds a new scoped access. There is also the case for pre-installed software on a fresh operating system install, as well as for image-based update systems that just work off filesystem images and never execute app specific code at install time.
That said, non-interactive programs might want some way to pre-flight these permission checks, so they can avoid blocking on them if they are pulling in credentials non-interactively. That said, I'm not sure whether this is a supported use case given the desire for user presence checking on Passkeys.
Other sorting
More for the registration use case but should probably remember the last used transport across origins as well. I suspect most people will have one transport they use for most things rather than switching transport for every origin.
All reactions
Thanks for the feedback, @Fraetor!
Does ambient mode need any kind of UI for the system component? Isn't it just a background check against "known" credential sources, and the browser handles all the UI?
The way that Chrome has implemented it, the UI is all in the browser. But I have a vision to move this beyond the browser and let the system do it for you. This is particularly helpful for smaller browsers, as they would just need to implement the API to call the Ambient UI, and the system would draw it for them, so we wouldn't need bespoke UIs for all the browsers and apps that need it.
That said, I'm not sure whether this is a supported use case given the desire for user presence checking on Passkeys.
Yeah, the Credential portal and credentialsd is about user-mediated credential access. service/scripting access is out of scope, as there are other means to do that (keyring, secret service, secret portal, credential manager APIs, etc.)
All reactions
It is commonly quite difficult to undo selecting "Never", as it often requires diving deep into uncommon settings menus.
On Android, I've seen the well designed apps that provide convenient ui for managing their own required permissions, allowing user to request them as needed. To enable this, there have to be an API on the system permission manger side for the app to list currently granted permissions and their time/scope limits.
All reactions
Some screenshots from macOS
Create a passkey
I have my computer configured with Bitwarden as a native passkey provider, so it shows up as the primary place to store new passkeys. That's good, because a synced passkey manager is a safe and useful default for average users.
The domain, username, and passkey provider name are displayed, and they have quotes around them, I believe to prevent injecting other text.
Screenshot 2026年07月30日 at 9 42 56 AMClicking continue shows the passkey provider UI for selecting. In this case, since the passkey provider was given a single credential, it didn't show any provider-specific UI and launched the user verification dialog.
Screenshot 2026年07月30日 at 9 43 57 AMViewing other devices for create
From the More Options
Screenshot 2026年07月30日 at 9 43 10 AM
Signing in
The browser requests a passkey, and the OS shows this screen. It uses my credential in the autofill list from my default credential provider.
Screenshot 2026年07月30日 at 9 44 33 AMSigning in with other methods
"More from Bitwarden..." would open the passkey provider's UI to choose from a list rather than sending a single credential to autofill.
Screenshot 2026年07月30日 at 9 44 39 AMSign in when multiple credentials match
Types of the credential ("passkey") are identified, as well as username and domain. The provider is only indicated by icon here.
Screenshot 2026年07月30日 at 9 46 39 AMSign in with QR code
I didn't capture a register with QR code flow, but it is very similar.
There is both a back button and a cancel button. Also note that this requires a click to activate; other clients, like Chrome, just show the QR code right away next to other mechanisms to choose from.
Screenshot 2026年07月30日 at 9 46 52 AMConnecting with a spinner shows after the user scans the QR code with another device, and the 2 devices "notice" each other.
Screenshot 2026年07月30日 at 9 48 32 AMAfter the devices are connected, the user is prompted to finish on the other device. When complete, the dialog closes, and they're sent back to the browser.
Screenshot 2026年07月30日 at 9 48 37 AMSign in with security key
The user must tap the device in order to select it, then enter the PIN, then touch it again to complete.
The user can skip straight to the user PIN screen by pressing their key as soon as the dialog starts, so they can avoid a click.
Windows Hello does this differently, but I don't have a machine to generate screenshots with.
Screenshot 2026年07月30日 at 9 47 08 AM Screenshot 2026年07月30日 at 9 47 32 AM Screenshot 2026年07月30日 at 9 47 40 AM