Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetpack: Account Protection #40925

Open
wants to merge 46 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d20732c
Add account protection package
dkmyta Jan 9, 2025
f8b11f6
Initialize project branch
dkmyta Jan 9, 2025
50d7e71
Update lock files
dkmyta Jan 17, 2025
716a6b0
Fix versions
dkmyta Jan 17, 2025
09fd9d2
Merge branch 'trunk' into add/packages/account-protection
dkmyta Jan 20, 2025
dde199a
Merge branch 'add/packages/account-protection' into add/account-prote…
dkmyta Jan 20, 2025
4b5550a
Update phan baseline
dkmyta Jan 21, 2025
2c9a0e8
Merge branch 'add/packages/account-protection' into add/account-prote…
dkmyta Jan 21, 2025
ce55671
Merge branch 'trunk' into add/account-protection
dkmyta Jan 24, 2025
6cbe1cc
Jetpack: Add Account Protection security settings (#40938)
dkmyta Jan 24, 2025
1ecf4df
Protect: Add Account Protection settings (#40942)
dkmyta Jan 24, 2025
1ec2c34
Account Protection: Add password detection flow (#41105)
dkmyta Jan 24, 2025
639a306
Account Protection: Remove strict mode (#41316)
dkmyta Jan 29, 2025
98c2064
Account Protection: Update password detection flow (#41365)
dkmyta Jan 30, 2025
98a8ba7
Account Protection: Add tests for newly added code (#41463)
ArSn Jan 31, 2025
e4c9b48
Jetpack: Update Account Protection copy (#41404)
dkmyta Jan 31, 2025
90f3e8a
Protect: Update Account Protection copy (#41402)
dkmyta Jan 31, 2025
22326bf
Rebase
dkmyta Jan 31, 2025
22e369e
Merge branch 'trunk' into add/account-protection
dkmyta Jan 31, 2025
7c669bf
Add wordbless dep, update consumer lock files
dkmyta Feb 2, 2025
73c5326
Allow core installer
dkmyta Feb 2, 2025
cdf66ba
Update lock files
dkmyta Feb 2, 2025
9435aa8
Account Protection: Fix invalid auth early return (#41652)
dkmyta Feb 11, 2025
e03a3f1
Reset to base (#41691)
dkmyta Feb 11, 2025
95f80c1
Merge branch 'trunk' into add/account-protection
dkmyta Feb 11, 2025
9032fde
Account Protection: Restore JetpackTestEnvironment (#41736)
nateweller Feb 12, 2025
933f0db
Account Protection: Add password validation (#41401)
dkmyta Feb 12, 2025
e3e192d
Protect: Fix Account Protection initial toggle state on activation (#…
dkmyta Feb 12, 2025
b44b207
Fix BFP recovery process conflict (#41739)
dkmyta Feb 12, 2025
5fe6dac
Account Protection: Add custom password strength meter (#41485)
dkmyta Feb 13, 2025
132417b
Improve the display of error notices on the password detection screen…
dkmyta Feb 13, 2025
547328a
Account Protection: Improve auth success flow (#41727)
dkmyta Feb 15, 2025
6d60099
Account Protection: clean up changelogs (#41833)
nateweller Feb 16, 2025
323bc99
Update projects/plugins/jetpack/modules/account-protection.php
dkmyta Feb 16, 2025
10f5295
Update projects/packages/account-protection/src/class-password-manage…
dkmyta Feb 16, 2025
fd2cb1c
Update projects/plugins/jetpack/modules/account-protection.php
dkmyta Feb 16, 2025
6478ee4
Account Protection: Add Settings Class (#41829)
nateweller Feb 16, 2025
7ff6b18
Account Protection: Disable setting in Protect in unsupported environ…
nateweller Feb 16, 2025
715fe15
Account Protection: Disable setting in Jetpack in unsupported environ…
nateweller Feb 16, 2025
7d83d5f
Adjust account protection settings UI in Jetpack (#41832)
nateweller Feb 16, 2025
d507e5b
Protect: Fix unsupported environment notice display while toggling (…
dkmyta Feb 18, 2025
05491e7
Add optimistic update revert, remove async from sync function (#41878)
nateweller Feb 18, 2025
908ae9a
Jetpack E2E: add account protection tests (#41835)
nateweller Feb 20, 2025
e6ee25f
Merge remote-tracking branch 'origin/trunk' into add/account-protection
nateweller Feb 20, 2025
0cbee68
Account Protection: Fix interim-login handling (#41924)
dkmyta Feb 20, 2025
d32f169
Account Protection: Improve strength meter implementation (#41802)
dkmyta Feb 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Add initial account protection features
4 changes: 3 additions & 1 deletion projects/packages/account-protection/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.2"
"php": ">=7.2",
"automattic/jetpack-connection": "@dev",
"automattic/jetpack-status": "@dev"
},
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
Expand Down
4 changes: 4 additions & 0 deletions projects/packages/account-protection/src/assets/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions projects/packages/account-protection/src/assets/cross.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions projects/packages/account-protection/src/assets/info.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions projects/packages/account-protection/src/assets/jetpack-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions projects/packages/account-protection/src/assets/loading.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
232 changes: 228 additions & 4 deletions projects/packages/account-protection/src/class-account-protection.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,240 @@
<?php
/**
* Package description here
* Class used to define Account Protection.
*
* @package automattic/jetpack-account-protection
*/

namespace Automattic\Jetpack;
namespace Automattic\Jetpack\Account_Protection;

use Automattic\Jetpack\Modules;

/**
* Class description.
* Class Account_Protection
*/
class Account_Protection {
const PACKAGE_VERSION = '0.1.0-alpha';
const ACCOUNT_PROTECTION_MODULE_NAME = 'account-protection';

/**
* Flag to track if hooks have been registered.
*
* @var bool
*/
private static $hooks_registered = false;

/**
* Modules instance.
*
* @var Modules
*/
private $modules;

/**
* Password detection instance.
*
* @var Password_Detection
*/
private $password_detection;

/**
* Password manager instance
*
* @var Password_Manager
*/
private $password_manager;

/**
* Password_Strength_Meter instance
*
* @var Password_Strength_Meter
*/
private $password_strength_meter;

/**
* Account_Protection constructor.
*
* @param ?Modules $modules Modules instance.
* @param ?Password_Detection $password_detection Password detection instance.
* @param ?Password_Manager $password_manager Password manager instance.
* @param ?Password_Strength_Meter $password_strength_meter Password strength meter instance.
*/
public function __construct( ?Modules $modules = null, ?Password_Detection $password_detection = null, ?Password_Manager $password_manager = null, ?Password_Strength_Meter $password_strength_meter = null ) {
$this->modules = $modules ?? new Modules();
$this->password_detection = $password_detection ?? new Password_Detection();
$this->password_manager = $password_manager ?? new Password_Manager();
$this->password_strength_meter = $password_strength_meter ?? new Password_Strength_Meter();
}

/**
* Initializes the configurations needed for the account protection module.
*
* @return void
*/
public function init(): void {
if ( self::$hooks_registered ) {
return;
}

$this->register_hooks();

if ( $this->is_enabled() ) {
$this->register_runtime_hooks();
}

self::$hooks_registered = true;
}

/**
* Register hooks for module activation and environment validation.
*
* @return void
*/
protected function register_hooks(): void {
// Account protection activation/deactivation hooks
add_action( 'jetpack_activate_module_' . self::ACCOUNT_PROTECTION_MODULE_NAME, array( $this, 'on_account_protection_activation' ) );
add_action( 'jetpack_deactivate_module_' . self::ACCOUNT_PROTECTION_MODULE_NAME, array( $this, 'on_account_protection_deactivation' ) );

// Do not run in unsupported environments
add_action( 'jetpack_get_available_modules', array( $this, 'remove_module_on_unsupported_environments' ) );
add_action( 'jetpack_get_available_standalone_modules', array( $this, 'remove_standalone_module_on_unsupported_environments' ) );
}

/**
* Register hooks for runtime operations.
*
* @return void
*/
protected function register_runtime_hooks(): void {
// Validate password after successful login
add_action( 'wp_authenticate_user', array( $this->password_detection, 'login_form_password_detection' ), 10, 2 );

// Handle password detection login failure
add_action( 'wp_login_failed', array( $this->password_detection, 'handle_password_detection_validation_error' ), 10, 2 );

// Add password detection flow
add_action( 'login_form_password-detection', array( $this->password_detection, 'render_page' ), 10, 2 );
add_action( 'wp_enqueue_scripts', array( $this->password_detection, 'enqueue_styles' ) );

// Add password validation
add_action( 'user_profile_update_errors', array( $this->password_manager, 'validate_profile_update' ), 10, 3 );
add_action( 'validate_password_reset', array( $this->password_manager, 'validate_password_reset' ), 10, 2 );

// Update recent passwords list
add_action( 'profile_update', array( $this->password_manager, 'on_profile_update' ), 10, 2 );
add_action( 'after_password_reset', array( $this->password_manager, 'on_password_reset' ), 10, 1 );

// Enqueue password strength meter scripts
add_action( 'admin_enqueue_scripts', array( $this->password_strength_meter, 'enqueue_jetpack_password_strength_meter_profile_script' ) );
add_action( 'login_enqueue_scripts', array( $this->password_strength_meter, 'enqueue_jetpack_password_strength_meter_reset_script' ) );

// AJAX endpoint for password validation
add_action( 'wp_ajax_validate_password_ajax', array( $this->password_strength_meter, 'validate_password_ajax' ) );
add_action( 'wp_ajax_nopriv_validate_password_ajax', array( $this->password_strength_meter, 'validate_password_ajax' ) );
}

/**
* Activate the account protection on module activation.
*
* @return void
*/
public function on_account_protection_activation(): void {
// Activation logic can be added here
}

/**
* Deactivate the account protection on module deactivation.
*
* @return void
*/
public function on_account_protection_deactivation(): void {
// Deactivation logic can be added here
}

/**
* Determines if the account protection module is enabled on the site.
*
* @return bool
*/
public function is_enabled(): bool {
return $this->modules->is_active( self::ACCOUNT_PROTECTION_MODULE_NAME );
}

/**
* Enables the account protection module.
*
* @return bool
*/
public function enable(): bool {
// Return true if already enabled.
if ( $this->is_enabled() ) {
return true;
}
return $this->modules->activate( self::ACCOUNT_PROTECTION_MODULE_NAME, false, false );
}

/**
* Disables the account protection module.
*
* @return bool
*/
public function disable(): bool {
// Return true if already disabled.
if ( ! $this->is_enabled() ) {
return true;
}
return $this->modules->deactivate( self::ACCOUNT_PROTECTION_MODULE_NAME );
}

/**
* Determines if Account Protection is supported in the current environment.
*
* @return bool
*/
public function is_supported_environment(): bool {
// Do not run when killswitch is enabled
if ( defined( 'DISABLE_JETPACK_ACCOUNT_PROTECTION' ) && DISABLE_JETPACK_ACCOUNT_PROTECTION ) {
return false;
}

return true;
}

/**
* Disables the Account Protection module when on an unsupported platform in Jetpack.
*
* @param array $modules Filterable value for `jetpack_get_available_modules`.
*
* @return array Array of module slugs.
*/
public function remove_module_on_unsupported_environments( array $modules ): array {
if ( ! $this->is_supported_environment() ) {
// Account protection should never be available on unsupported platforms.
unset( $modules[ self::ACCOUNT_PROTECTION_MODULE_NAME ] );
}

return $modules;
}

/**
* Disables the Account Protection module when on an unsupported platform in a standalone plugin.
*
* @param array $modules Filterable value for `jetpack_get_available_standalone_modules`.
*
* @return array Array of module slugs.
*/
public function remove_standalone_module_on_unsupported_environments( array $modules ): array {
if ( ! $this->is_supported_environment() ) {
// Account Protection should never be available on unsupported platforms.
$modules = array_filter(
$modules,
function ( $module ) {
return $module !== self::ACCOUNT_PROTECTION_MODULE_NAME;
}
);

}

const PACKAGE_VERSION = '0.1.0-alpha';
return $modules;
}
}
27 changes: 27 additions & 0 deletions projects/packages/account-protection/src/class-config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
/**
* Class used to define Config.
*
* @package automattic/jetpack-account-protection
*/

namespace Automattic\Jetpack\Account_Protection;

/**
* Class Config
*/
class Config {
// Password Detection Constants
public const PASSWORD_DETECTION_TRANSIENT_PREFIX = 'password_detection';
public const PASSWORD_DETECTION_ERROR_CODE = 'password_detection_validation_error';
public const PASSWORD_DETECTION_EMAIL_SENT_EXPIRATION = 600; // 10 minutes
public const PASSWORD_DETECTION_MAX_RESEND_ATTEMPTS = 3;

// Password Manager Constants
public const PASSWORD_MANAGER_RECENT_PASSWORD_HASHES_USER_META_KEY = 'jetpack_account_protection_recent_password_hashes';
public const PASSWORD_MANAGER_RECENT_PASSWORDS_LIMIT = 10;

// Validation Service Constants
public const VALIDATION_SERVICE_MIN_LENGTH = 6;
public const VALIDATION_SERVICE_MAX_LENGTH = 150;
}
Loading
Loading