Skip to content

#953 - Email account owner when two-factor settings change - #1001

Open
masteradhoc wants to merge 7 commits into
masterfrom
provider-notifications
Open

masteradhoc wants to merge 7 commits into
masterfrom
provider-notifications

Conversation

@masteradhoc

@masteradhoc masteradhoc commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

What?

Emails the account owner whenever their two-factor authentication methods change — a provider is activated or deactivated via the profile page or via WP-CLI (wp two-factor enable/disable).

Fixes #953
Related #476

Why?

Enrolling or removing a factor destroys the account's other active sessions (wp_destroy_other_sessions() / WP_Session_Tokens::destroy_all()) with no notification — indistinguishable from an unauthorized logout, especially when an administrator makes the change on a user's behalf. #953 asked for an email notification here, following the same pattern already used by this plugin's compromised-password-reset emails. core trac #63927 — which adds an equivalent notification when a new application password is created — was cited as supporting precedent for adding this kind of security-event email.

How?

  • Added Two_Factor_Core::notify_user_two_factor_settings_changed( $user, $enabled_providers, $existing_providers ), which diffs the before/after provider lists and emails the account owner listing which methods were activated/deactivated, plus a line noting that all open sessions were logged out.
  • The email is always sent when providers actually change — there is no boolean send/skip gate, since this is a security notification the account owner should always receive. Only the content is filterable, via two_factor_settings_changed_email (subject/message/headers/recipient).
  • Wired into both places that mutate a user's enabled providers:
    • user_two_factor_options_update() (the profile-page save path)
    • The WP-CLI enable/disable commands, via the shared destroy_sessions_if_providers_changed() helper, so a change made out-of-band via the CLI is reported the same way a UI change would be.
  • Subject line includes the site name ([Site Name] Your two-factor authentication settings have changed), matching the bracketed-subject convention WP core uses for its own account-security emails.

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Sonnet 5
Used for: Full implementation (new method, call-site wiring, PHPUnit tests) drafted by the assistant per my direction across several review rounds (wording, removing the session-destroyed conditional, subject line, @since versioning). I reviewed and directed every change before it was committed.

Testing Instructions

  1. npm run env start && npm run build
  2. Enable MailHog or a similar local mail catcher (wp-env ships with one — check http://localhost:8025).
  3. As a user, go to your profile → Two-Factor Options, enable a method (e.g. Email), and save. Confirm you receive an email listing the change.
  4. Add/remove a second method and save again — confirm each change sends its own email.
  5. As an admin, edit another user's 2FA settings and save — confirm the email goes to that user, not to you.
  6. Via WP-CLI: wp two-factor enable <user> Two_Factor_Email and wp two-factor disable <user> Two_Factor_Email — confirm each sends the same notification.
  7. Run the test suite: npm test — new coverage lives in tests/class-two-factor-core.php (search for notify_user_two_factor_settings_changed / settings_changed_notification).

Screenshots or screencast

N/A — no UI changes.

Changelog Entry

Added - Email the account owner when their two-factor authentication methods are activated or deactivated, whether the change was made via the profile page or WP-CLI.

Open WordPress Playground Preview

@masteradhoc masteradhoc added this to the 0.18.0 milestone Sep 27, 2026
@masteradhoc masteradhoc self-assigned this Sep 27, 2026
@masteradhoc masteradhoc changed the title Provider notifications #953 - Email account owner when two-factor settings change Sep 27, 2026
@masteradhoc
masteradhoc marked this pull request as ready for review September 27, 2026 11:42
@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: masteradhoc <masteradhoc@git.wordpress.org>
Co-authored-by: kasparsd <kasparsd@git.wordpress.org>
Co-authored-by: dknauss <dpknauss@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

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.

🟡 Changes recommended

Some provider-change paths miss notifications, and the email inaccurately claims that all sessions were logged out.

4 open issues
What changed in this PR

Adds account-owner email notifications for two-factor provider changes, addressing the silent security changes described in #953.

Changes:

  • Adds provider-change emails with filterable content and site-branded subjects.
  • Connects notifications to profile saves and the shared CLI session-reset helper.
  • Adds notification tests and mail-fixture cleanup.
File Description
tests/​class-two-factor-core.php Tests notification delivery, recipients, and content filtering.
CLI/​class-two-factor-cli-command.php Adds notifications to the provider-change helper.
class-two-factor-core.php Builds notification emails and sends them after profile changes.

Review effort: Balanced

WP_Session_Tokens::get_instance( $user->ID )->destroy_all();
}

Two_Factor_Core::notify_user_two_factor_settings_changed( $user, $providers_after, $providers_before );
Comment thread class-two-factor-core.php
return false;
}

$supported_providers = self::get_supported_providers_for_user( $user->ID );
Comment thread class-two-factor-core.php
// (see the conditions in user_two_factor_options_update()), the account owner is told
// their sessions were logged out: it's true often enough, and simpler than trying to
// explain the exact conditions under which the plugin invalidates other sessions.
$changes[] = __( 'All open sessions have been logged out.', 'two-factor' );
Comment thread class-two-factor-core.php
}
}

self::notify_user_two_factor_settings_changed( $user, array_keys( $enabled_providers ), $existing_providers );
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.

Enrolling a second factor destroys the user's other sessions and sends no notification

3 participants