Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Ecosystem-aware passkey onboarding#448

Open
spin-drift wants to merge 6 commits into
voidauth:mainvoidauth/voidauth:mainfrom
spin-drift:passkeys4all-heavyspin-drift/voidauth:passkeys4all-heavyCopy head branch name to clipboard
Open

Ecosystem-aware passkey onboarding#448
spin-drift wants to merge 6 commits into
voidauth:mainvoidauth/voidauth:mainfrom
spin-drift:passkeys4all-heavyspin-drift/voidauth:passkeys4all-heavyCopy head branch name to clipboard

Conversation

@spin-drift
Copy link
Copy Markdown

@spin-drift spin-drift commented May 27, 2026

Description

Major changes

  • Device ecosystem is stored and used for prompting, so e.g. a user who registers (or declines) a passkey on macOS isn't prompted again on iPhone, but would be on a Windows laptop.
  • Passkey prompt seen/skipped status is now stored in DB, with the existing localStorage checks kept for backwards-compatibility. Migration is included.

Database changes

Two new (nullable) columns:

  • passkey.ecosystem records which ecosystem a passkey was registered on: 'apple', 'windows', 'android', or null for unknown.
  • user.passkeySkippedEcosystems is a CSV of ecosystems where the user has explicitly declined, stored server-side so "skip" persists across devices.

A new endpoint (POST /api/user/passkey/skip) records the skip server-side.

Client logic

  • PasskeySupport uses OS detection (UAParser) to populate ecosystem:

    • iOS / macOS: 'apple'
    • Windows: 'windows'
    • Android: 'android'
    • everything else: undefined (falls back to legacy global localStorage behavior)
  • shouldAskPasskey drops the isPrivileged requirement and checks (in order):

    • No platform authenticator available?: don't ask
    • Server says user already has a passkey for this ecosystem?: don't ask
    • localStorage says user has seen/registered a passkey on this device?: don't ask
    • Server says user has skipped this ecosystem?: don't ask
    • localStorage says user has skipped on this device?: don't ask
    • Otherwise?: ask

Notes

  • Users with cross-platform passkey managers will still get prompted once per new device ecosystem they log in on. This is because backedUp will be true for both first- and third-party managers, and basing the check on backedUp = true would defeat the purpose of this PR (since it doesn't matter whether a passkey is backed up if it's not usable on the device a user is currently on). This feels acceptable over implementing AAGUID checking for something this small.

  • Users relying on hardware keys won't be prompted. platformAuthenticatorIsAvailable() only detects OS-native biometric authenticators, so support.enabled will be false. This shouldn't be a problem, since the existing key entry flow should handle that separately.

  • CSV for skipped ecosystems. We're only storing a handful of values, so I just used the same pattern as passkey.transports. Ecosystem values are validated against /^[a-z0-9-]+$/ to prevent comma injection into the CSV field.

Related Tickets & Documents

#447

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.