Skip to content

feat(settings): add passkey rename ui#20850

Merged
vpomerleau merged 1 commit into
mainfrom
FXA-13962
Jul 15, 2026
Merged

feat(settings): add passkey rename ui#20850
vpomerleau merged 1 commit into
mainfrom
FXA-13962

Conversation

@vpomerleau

@vpomerleau vpomerleau commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Because

  • Passkeys are auto-named generically at creation (e.g. "Passkey", "Platform
    Passkey"), and users had no way to rename them to something meaningful.
  • Renaming is non-destructive, so it should not require an MFA/OTP step-up the
    way passkey removal does.

This pull request

  • Adds a passkey rename control in packages/fxa-settings/src/components/Settings/SubRow/index.tsx:
    the passkey name and a decorative pencil form a single button that opens a rename
    modal dialog (PasskeyRenameModal, reusing the same Modal component as the delete dialog)
    with Save/Cancel.
  • Changes PATCH /passkey/{credentialId} in packages/fxa-auth-server/lib/routes/passkeys.ts
    from the mfa strategy to verifiedSessionToken; the delete route keeps its MFA guard.
  • Adds a sessionPatch helper in packages/fxa-auth-client/lib/client.ts and repoints
    renamePasskey to a session token; Account.renamePasskey uses the cached session token.
  • Validates the new name on submit (non-empty, max 255, display-safe unicode, plus a
    client-side duplicate-name guard) and shows an inline error without calling the API until valid.
  • Adds Glean passkey_rename view/submit/success/error events (fxa-ui-metrics.yaml + regenerated
    web bindings) and new FTL strings in SubRow/en.ftl.

Issue that this pull request solves

Closes: FXA-13962

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

How to review (Optional)

  • Key files/areas to focus on: the auth-strategy change in packages/fxa-auth-server/lib/routes/passkeys.ts
    (rename → verified session token; delete unchanged) and the rename modal + validation in
    packages/fxa-settings/src/components/Settings/SubRow/index.tsx.
  • Suggested review order: passkeys.tsclient.tsAccount.tsSubRow/index.tsx → tests.
  • Risky or complex parts: the rename-route auth downgrade — verified session enforces AAL2 and the
    handler scopes the DB write by uid + credentialId, so ownership is server-enforced.

Screenshots (Optional)

Please attach the screenshots of the changes made in case of change in user interface.

image image

Other information (Optional)

Any other information that is important to this pull request.

@vpomerleau vpomerleau force-pushed the FXA-13962 branch 4 times, most recently from f8e9e88 to 3b6a1a4 Compare July 13, 2026 20:57
@vpomerleau vpomerleau requested a review from Copilot July 13, 2026 20:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end support for renaming passkeys from the Settings UI, including client/server auth changes and new telemetry, so users can give passkeys meaningful names without an MFA step-up.

Changes:

  • Adds an inline “rename” trigger + modal with client-side validation and UX error handling for passkey names.
  • Switches the auth-server passkey rename route from MFA JWT to verified session token auth; updates auth-client/settings Account usage accordingly.
  • Introduces new Glean metrics + bindings and localized strings for rename flows; adds icon asset for the edit affordance.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/fxa-shared/metrics/glean/web/index.ts Adds generated event-name mappings for passkey rename telemetry.
packages/fxa-shared/metrics/glean/web/accountPref.ts Adds generated Glean event metric types for rename view/success/error.
packages/fxa-shared/metrics/glean/fxa-ui-metrics.yaml Declares new account_pref passkey rename events and extras.
packages/fxa-settings/src/models/Account.ts Updates renamePasskey to use verified session token instead of MFA JWT.
packages/fxa-settings/src/models/Account.test.ts Adds unit tests for Account.renamePasskey session-token usage and refresh behavior.
packages/fxa-settings/src/lib/types.ts Removes the now-unused MfaReason.renamePasskey.
packages/fxa-settings/src/lib/glean/index.ts Wires new passkey rename events into the settings-side Glean recorder.
packages/fxa-settings/src/lib/glean/index.test.ts Adds tests ensuring rename events are recorded with expected names/extras.
packages/fxa-settings/src/constants/index.tsx Adds display-safe unicode regex that permits non-BMP characters (emoji).
packages/fxa-settings/src/components/Settings/SubRow/index.tsx Adds inline rename control + rename modal + shared validation helper.
packages/fxa-settings/src/components/Settings/SubRow/index.test.tsx Adds component tests for rename modal behavior, validation, and telemetry calls.
packages/fxa-settings/src/components/Settings/SubRow/index.stories.tsx Updates story to support rename behavior and exercise duplicate-name validation.
packages/fxa-settings/src/components/Settings/SubRow/en.ftl Adds localized strings for rename UI, validation messages, and outcomes.
packages/fxa-settings/src/components/Icons/index.tsx Exports a new pencil/edit icon component.
packages/fxa-settings/src/components/Icons/icon_pencil.min.svg Adds the pencil SVG asset.
packages/fxa-settings/src/components/Icons/en.ftl Adds the icon aria-label string for the edit icon.
packages/fxa-auth-server/lib/routes/passkeys.ts Changes PATCH /passkey/{credentialId} auth to verified session token strategies.
packages/fxa-auth-client/lib/client.ts Adds sessionPatch helper and updates renamePasskey to use session token auth.
Comments suppressed due to low confidence (1)

packages/fxa-auth-server/lib/routes/passkeys.ts:996

  • The rename route validates name only by length, but the UI now enforces display-safe unicode (including non-BMP). To keep server-side validation authoritative (and consistent with other user-visible name fields like devices), add the same regex validation to the route payload schema.
        pre: [{ method: passkeysEnabledCheck }],
        auth: {
          strategies: ['verifiedSessionTokenBearer', 'verifiedSessionToken'],
          payload: false,
        },
        validate: {
          params: isA.object({
            credentialId: base64urlCredentialId().required(),
          }),
          payload: isA.object({
            name: isA.string().min(1).max(255).required(),
          }),
        },

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/fxa-settings/src/components/Settings/SubRow/index.tsx
Comment thread packages/fxa-settings/src/components/Settings/SubRow/en.ftl Outdated
@vpomerleau vpomerleau force-pushed the FXA-13962 branch 2 times, most recently from e03adff to afd9220 Compare July 13, 2026 22:21
@vpomerleau vpomerleau changed the title feat(settings): add inline passkey rename feat(settings): add passkey rename ui Jul 13, 2026
@vpomerleau vpomerleau marked this pull request as ready for review July 14, 2026 15:05
@vpomerleau vpomerleau requested review from a team as code owners July 14, 2026 15:05
});

it('returns undefined for a name with non-BMP characters (e.g. emoji)', () => {
expect(validatePasskeyName('My Passkey \u{1F510}')).toBeUndefined();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is valid?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, intentional. I'll re-word the test case so it's easier to read. The validation here matches the auth-server validator (DISPLAY_SAFE_UNICODE_WITH_NON_BMP) — the same rule used for device names.

const jwt = this.getCachedJwtByScope('passkey');
await this.withLoadingStatus(
this.authClient.renamePasskey(jwt, credentialId, name)
this.authClient.renamePasskey(sessionToken()!, credentialId, name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something we need to address in this PR, but IMO using ! like this circumvents type safety.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling this out. We have a lot of this pattern in the file, but that doesn't mean I need to follow it. Fixed.

@dschom dschom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

send_in_pings:
- events
notification_emails:
- vzare@mozilla.com

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we need vesta on these anymore, tbh

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering about that - we may want to update globally for all metrics.

Because:
* Passkeys are auto-named generically at creation and users had no way to
  rename them afterward.

This commit:
* Adds a rename control (passkey name + pencil) on the passkey SubRow that
  opens a modal dialog with Save/Cancel.
* Switches PATCH /passkey/{credentialId} from the MFA JWT strategy to a
  verified session token; rename is non-destructive, so no OTP step-up.
* Adds a sessionPatch auth-client helper and repoints renamePasskey to the
  session token; Account.renamePasskey uses the cached session token.
* Validates on submit (non-empty, max 255, display-safe unicode, plus a
  client-side duplicate-name guard) with an inline error message.
* Adds Glean rename view/submit/success/error events, FTL strings, and tests.

Closes #FXA-13962
@vpomerleau vpomerleau merged commit 93960f1 into main Jul 15, 2026
21 checks passed
@vpomerleau vpomerleau deleted the FXA-13962 branch July 15, 2026 17:19
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.

4 participants