Skip to content

✨ Add app passwords for mail clients - #1391

Draft
t2d wants to merge 6 commits into
mainfrom
feat/app-passwords
Draft

t2d wants to merge 6 commits into
mainfrom
feat/app-passwords

Conversation

@t2d

@t2d t2d commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Goal

First step towards enforcing TOTP in the Keycloak realm systemli: mail clients can't do TOTP, so users need separate passwords for them.

Changes

  • Users create named app passwords under Account settings → App Passwords. The password is shown once; only its SHA-256 hash is stored.
  • App passwords are accepted by the Dovecot passdb, Postfix SASL and Roundcube aliases APIs. They are not accepted by the web login, the Keycloak validate API or app:users:mailcrypt.
  • MailCrypt: each app password stores its own copy of the private key, encrypted with the app password (same pattern as the recovery token). Creating one needs the main password, and creates a MailCrypt key if the user has none.
  • App password logins update the last login time but don't dispatch LoginEvent, so they never create MailCrypt keys or trigger HIBP checks.
  • App passwords survive password change and recovery (the MailCrypt key stays the same). They are deleted on admin reset (new key) and account deletion.
  • Metrics: userli_users_app_password_total (users with at least one app password) and userli_app_passwords_total, next to userli_users_twofactor_total.
  • Docs: new user page, plus notes in the security, delete and admin user docs.

Testing

  • PHPUnit and Behat cover manager, auth handler, revocation, all four APIs and the account UI.
  • Checked manually against the dev Dovecot: IMAP login with an app password for mailcrypt@example.org works and reads a mail that is stored encrypted on disk. Wrong passwords and other users' app passwords are rejected.

Screenshots

Settings card
App passwords
New app password

🤖 Generated with Claude Code

t2d and others added 2 commits October 18, 2026 17:17
Users can create named app passwords in the account settings. They are
accepted by the Dovecot, Postfix and Roundcube APIs, but not by the web
login or Keycloak. Each app password stores its own copy of the MailCrypt
private key. App passwords are deleted on admin reset and account deletion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@t2d t2d added enhancement New feature or request security ux/ui documentation Software is more than code labels Oct 18, 2026
t2d and others added 4 commits October 18, 2026 21:05
The password field only confirms it's the user. Label it "Current password"
and explain that the app password is generated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Count users with app passwords and app passwords in total, next to the 2FA
metric, to follow the move to app passwords before enforcing TOTP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reloading the page after creating an app password resubmitted the form and
created a second one with the same name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

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

Labels

documentation Software is more than code enhancement New feature or request security ux/ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant