Skip to content

🔐 Require password confirmation for OpenPGP key replacement#1256

Draft
t2d wants to merge 6 commits into
mainfrom
feature/issue-1168-openpgp-replace-password
Draft

🔐 Require password confirmation for OpenPGP key replacement#1256
t2d wants to merge 6 commits into
mainfrom
feature/issue-1168-openpgp-replace-password

Conversation

@t2d
Copy link
Copy Markdown
Contributor

@t2d t2d commented Apr 19, 2026

Summary

  • Require password confirmation when uploading an OpenPGP key for an identity that already has a key.
  • Keep first-time OpenPGP uploads unchanged (no password required) and keep delete behavior as-is.
  • Split the replacement flow into two chained overlays: step 1 takes the key file/text, step 2 asks for the account password with distinct copy and styling so it cannot be mistaken for the OpenPGP key's passphrase.
  • Add/adjust PHPUnit, Behat, and Vitest coverage.

Why

Issue #1168 points out inconsistent protection in the OpenPGP flow. Replacing an existing key is a sensitive action and should require step-up authentication. Keeping the account-password field in the same panel as the key-upload fields risked users reading it as "the passphrase for the key you're about to upload" — the dedicated overlay spells out that it is the Userli account password instead.

Screenshots

Step 1 — key upload (unchanged fields, primary button now reads Continue):

step-1-upload-overlay.png

Step 2 — account-password confirmation (only shown when replacing an existing key):

step-2-password-overlay.png

Testing

  • make phpunit
  • make vitest
  • php bin/behat --tags='@upload-openpgp-file-replace-valid-key,@upload-openpgp-file-replace-valid-key-password' (one scenario fails locally in this environment due to missing GPG binary)

t2d and others added 3 commits April 19, 2026 08:00
Co-authored-by: opencode <opencode@noreply.opencode.ai>
Co-authored-by: GitHub Copilot <copilot@noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the account-password step out of the upload modal and into a
visually distinct second overlay so it cannot be mistaken for the
OpenPGP key's passphrase. The new overlay has its own icon, copy, and
colour treatment and spells out that the field asks for the Userli
account password, not the key's passphrase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@t2d t2d force-pushed the feature/issue-1168-openpgp-replace-password branch from 25b6aa6 to 5a31080 Compare April 19, 2026 18:25
t2d and others added 2 commits April 19, 2026 20:29
- Name the default-exported class
- Mark static targets as readonly
- Replace void offsetHeight idiom with getBoundingClientRect() to force reflow

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

…odal

Restore the OpenPGP upload modal to upstream markup (no password field,
no "Continue" button) and lift the password-confirmation step into a
generic `_password_verification_modal.html.twig` partial used by both
the replace flow and all existing delete flows (alias, account, domain,
OpenPGP).

- New partial supports two modes:
  * Standalone (default) — emits its own <form> with CSRF token and
    POSTs to `modal_action`. Current delete flows keep working.
  * External form — when `external_form_id` is set, the password input
    and submit button are bound to a form elsewhere on the page via
    HTML5 `form=` attributes.

- New `openpgp-replace` Stimulus controller extends the generic modal:
  the "Replace" button fires `modal#open openpgp-replace#arm`; the
  controller intercepts the next submit of the upload form and shows
  this password modal, which then POSTs the upload payload together
  with the account password via the HTML5 `form=` binding. Arming is
  cleared on cancel / close or when the "Upload" button is used next.

- OpenPgpKeyType and its form model revert to upstream (no password
  field). The controller now reads the password from the raw request
  payload for the replace check.

- Copy tweaked to drop the product name ("Userli") and to not require
  an email interpolation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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