Skip to content

[iOS] Adding a passkey to an existing entry fills the username field (if empty) with the WebAuthn user.name #474

@nphlp

Description

@nphlp

Adding a passkey to an existing entry fills the username field (if empty) with the WebAuthn user.name

Context

I'm developing a website with WebAuthn support via the Better Auth Passkey plugin.
I want users to be able to add a Passkey to their account from their profile page.

Description

When the user adds a Passkey, I call await passkey.addPasskey({ name: string | undefined }).
The name parameter (e.g. "My super passkey") is optional and maps to the WebAuthn user.name.
If no name is provided, the Better Auth plugin falls back to the user's email (see Better Auth Passkey docs).

At that point, Proton Pass opens and lets me select an existing entry to associate the Passkey with.
Proton Pass iOS adds the Passkey to the selected entry, naming it with the WebAuthn user.name (either the custom name or the email fallback).
This part works as expected.

Problem

When saving the Passkey, if the selected entry has an empty username field, Proton Pass iOS fills it with the WebAuthn user.name (either the custom name or the email fallback).

My Proton Pass entry goes from:

// Before adding passkey
Site:     Example
Passkey:  (empty)
Email:    john-doe@example.com
Username: (empty)
Password: ********
URL:      https://example.com

// After adding passkey
Site:     Example
Passkey:  "My super passkey" or "john-doe@example.com"    ← correct, expected
Email:    john-doe@example.com
Username: "My super passkey" or "john-doe@example.com"    ← unexpected, filled with WebAuthn user.name
Password: ********
URL:      https://example.com

The WebAuthn user.name is a technical identifier from the registration ceremony (often the email, or a custom label like "My super passkey").
It is not a login username. Copying it into the entry's username field is incorrect.

On subsequent login with email/password, the username field can take priority over the email field and cause autofill issues.
For example:

// Login page autofill after passkey addition
Email:    "My super passkey"    ← username taking priority, wrong value
Password: ********

Expected behavior

Adding a Passkey to an existing entry should not modify the username field. An empty username should remain empty.

Code reference

The issue is in CreateAndAssociatePasskey.swift line 74:

let username = oldLoginData.username.isEmpty ? request.userName : oldLoginData.username

This fallback overwrites an empty username with the WebAuthn user.name, which is not the intended purpose of this field.

Note: Android and Chrome extension do not have this issue

AndroidAddPasskeyToItem.kt only appends the passkey to the passkeysList without modifying the login data (email, username, password).

Chrome extensionautosave.ts explicitly preserves the existing username/email when adding a passkey:

// In the UPDATE handler, when passkey is truthy, the existing value is preserved:
content.set(userIdKey, (value) => (passkey ? value : payload.userIdentifier));

Both Android and Chrome extension correctly leave the login entry's username untouched when associating a passkey. Only the iOS app overwrites it.

Environment

  • iPhone 11 Pro, latest iOS version
  • Chrome iOS app, latest version
  • Proton Pass iOS, latest version
  • Desktop browser extension: no issue, behavior is correct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions