From 46f3ebfa085c237e1d84d345f5b79dbc48175355 Mon Sep 17 00:00:00 2001 From: Leonardo Sameshima Taba Date: Mon, 21 Sep 2026 14:36:31 -0300 Subject: [PATCH 1/6] Sites API: expose the SSO "Require two-step authentication" setting Adds the `jetpack_sso_require_two_step` site option to the `/sites/%s` response so clients can tell which sites need two-step authentication before sending the user to WP Admin. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018e9mXu6SCNbHMu1JhySDRG --- ...d-site-option-jetpack-sso-require-two-step | 4 +++ ...class.wpcom-json-api-get-site-endpoint.php | 5 ++++ .../jetpack/sal/class.json-api-site-base.php | 9 +++++++ .../Jetpack_Site_Json_Api_Endpoints_Test.php | 27 +++++++++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 projects/plugins/jetpack/changelog/add-site-option-jetpack-sso-require-two-step diff --git a/projects/plugins/jetpack/changelog/add-site-option-jetpack-sso-require-two-step b/projects/plugins/jetpack/changelog/add-site-option-jetpack-sso-require-two-step new file mode 100644 index 000000000000..361423984d11 --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-site-option-jetpack-sso-require-two-step @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Sites API: return the "Require two-step authentication" SSO setting as the `jetpack_sso_require_two_step` site option. diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php index d47666a50662..c0d807d2ec08 100644 --- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php +++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-get-site-endpoint.php @@ -245,6 +245,7 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { 'wpcom_admin_interface', 'wpcom_classic_early_release', 'jetpack_recovery_mode_status', + 'jetpack_sso_require_two_step', 'apm_enabled', 'wpcom_ai_launchpad_enabled', 'wpcom_ai_launchpad_dismissed', @@ -321,6 +322,7 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint { 'wpcom_admin_interface', 'wpcom_classic_early_release', 'jetpack_recovery_mode_status', + 'jetpack_sso_require_two_step', 'apm_enabled', ); @@ -1026,6 +1028,9 @@ protected function render_option_keys( &$options_response_keys ) { case 'jetpack_recovery_mode_status': $options[ $key ] = $site->get_jetpack_recovery_mode_status(); break; + case 'jetpack_sso_require_two_step': + $options[ $key ] = $site->get_jetpack_sso_require_two_step(); + break; case 'apm_enabled': $options[ $key ] = $site->get_apm_enabled(); break; diff --git a/projects/plugins/jetpack/sal/class.json-api-site-base.php b/projects/plugins/jetpack/sal/class.json-api-site-base.php index 3e425d45cbe4..33bae687dce9 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-base.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-base.php @@ -1894,4 +1894,13 @@ public function get_jetpack_recovery_mode_status() { $status = get_option( 'jetpack_recovery_mode_status' ); return is_array( $status ) ? $status : null; } + + /** + * Whether WordPress.com accounts must have two-step authentication to log in through SSO. + * + * @return bool + */ + public function get_jetpack_sso_require_two_step() { + return (bool) get_option( 'jetpack_sso_require_two_step' ); + } } diff --git a/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php b/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php index f9a4516ed4b7..0320e190916f 100644 --- a/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php +++ b/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php @@ -70,6 +70,33 @@ public function test_get_site() { $this->assertArrayHasKey( 'jetpack_connection_active_plugins', $options ); } + /** + * The `jetpack_sso_require_two_step` option is returned as a boolean site option. + */ + public function test_get_site_jetpack_sso_require_two_step_option() { + global $blog_id; + + $editor = self::factory()->user->create_and_get( + array( + 'role' => 'editor', + ) + ); + + wp_set_current_user( $editor->ID ); + + $endpoint = $this->create_get_site_endpoint(); + + $response = $endpoint->callback( '', $blog_id ); + $this->assertFalse( ( (array) $response['options'] )['jetpack_sso_require_two_step'] ); + + update_option( 'jetpack_sso_require_two_step', '1' ); + + $response = $endpoint->callback( '', $blog_id ); + $this->assertTrue( ( (array) $response['options'] )['jetpack_sso_require_two_step'] ); + + delete_option( 'jetpack_sso_require_two_step' ); + } + /** * Test that trial flags are returned for sites that have them. * From 6bd74f4c9719d24204ce99f2a911baff994a3e25 Mon Sep 17 00:00:00 2001 From: Leonardo Sameshima Taba Date: Mon, 21 Sep 2026 15:22:09 -0300 Subject: [PATCH 2/6] Sites API: report the enforced two-step rule, not only the saved option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SSO checks `apply_filters( 'jetpack_sso_require_two_step', get_option( … ) )`, and Force_2FA hooks `__return_true` onto that filter. Run the option through the same filter so the site option matches what SSO enforces. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018e9mXu6SCNbHMu1JhySDRG --- .../plugins/jetpack/sal/class.json-api-site-base.php | 6 +++++- .../json-api/Jetpack_Site_Json_Api_Endpoints_Test.php | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-base.php b/projects/plugins/jetpack/sal/class.json-api-site-base.php index 33bae687dce9..fcd6730eb318 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-base.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-base.php @@ -1898,9 +1898,13 @@ public function get_jetpack_recovery_mode_status() { /** * Whether WordPress.com accounts must have two-step authentication to log in through SSO. * + * Mirrors what SSO enforces: the saved setting, run through the `jetpack_sso_require_two_step` + * filter that Force_2FA hooks into. Only meaningful while the SSO module is active. + * * @return bool */ public function get_jetpack_sso_require_two_step() { - return (bool) get_option( 'jetpack_sso_require_two_step' ); + /** This filter is documented in projects/packages/connection/src/sso/class-helpers.php */ + return (bool) apply_filters( 'jetpack_sso_require_two_step', get_option( 'jetpack_sso_require_two_step', false ) ); } } diff --git a/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php b/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php index 0320e190916f..333c367b3a2c 100644 --- a/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php +++ b/projects/plugins/jetpack/tests/php/json-api/Jetpack_Site_Json_Api_Endpoints_Test.php @@ -71,7 +71,8 @@ public function test_get_site() { } /** - * The `jetpack_sso_require_two_step` option is returned as a boolean site option. + * The `jetpack_sso_require_two_step` site option reports what SSO enforces: the saved + * setting, or `true` when the `jetpack_sso_require_two_step` filter forces it. */ public function test_get_site_jetpack_sso_require_two_step_option() { global $blog_id; @@ -95,6 +96,12 @@ public function test_get_site_jetpack_sso_require_two_step_option() { $this->assertTrue( ( (array) $response['options'] )['jetpack_sso_require_two_step'] ); delete_option( 'jetpack_sso_require_two_step' ); + add_filter( 'jetpack_sso_require_two_step', '__return_true' ); + + $response = $endpoint->callback( '', $blog_id ); + $this->assertTrue( ( (array) $response['options'] )['jetpack_sso_require_two_step'] ); + + remove_filter( 'jetpack_sso_require_two_step', '__return_true' ); } /** From e7e3fc448fec696affa38710bebff0328a72df05 Mon Sep 17 00:00:00 2001 From: Leonardo Sameshima Taba Date: Mon, 21 Sep 2026 18:43:17 -0300 Subject: [PATCH 3/6] Sites API: reword the two-step getter docblock Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018e9mXu6SCNbHMu1JhySDRG --- projects/plugins/jetpack/sal/class.json-api-site-base.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-base.php b/projects/plugins/jetpack/sal/class.json-api-site-base.php index fcd6730eb318..f10a9067080c 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-base.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-base.php @@ -1898,8 +1898,9 @@ public function get_jetpack_recovery_mode_status() { /** * Whether WordPress.com accounts must have two-step authentication to log in through SSO. * - * Mirrors what SSO enforces: the saved setting, run through the `jetpack_sso_require_two_step` - * filter that Force_2FA hooks into. Only meaningful while the SSO module is active. + * The `jetpack_sso_require_two_step` option is the "Require two-step authentication" + * checkbox in the SSO settings. The filter of the same name lets code override it, so + * this returns the same value SSO checks. SSO only enforces it while the module is active. * * @return bool */ From 8559551844a5e530cd76a15783ceb8dd2957cca9 Mon Sep 17 00:00:00 2001 From: Leonardo Sameshima Taba Date: Mon, 21 Sep 2026 18:47:02 -0300 Subject: [PATCH 4/6] Sites API: reword the two-step getter docblock Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018e9mXu6SCNbHMu1JhySDRG --- projects/plugins/jetpack/sal/class.json-api-site-base.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-base.php b/projects/plugins/jetpack/sal/class.json-api-site-base.php index f10a9067080c..ad22814e398d 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-base.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-base.php @@ -1900,7 +1900,8 @@ public function get_jetpack_recovery_mode_status() { * * The `jetpack_sso_require_two_step` option is the "Require two-step authentication" * checkbox in the SSO settings. The filter of the same name lets code override it, so - * this returns the same value SSO checks. SSO only enforces it while the module is active. + * this returns the same value checked by the SSO module. The requirement is only + * enforced while the module is active. * * @return bool */ From cdaa1202162394892353208c3cc529e12e5cacfa Mon Sep 17 00:00:00 2001 From: Leonardo Sameshima Taba Date: Mon, 21 Sep 2026 18:48:03 -0300 Subject: [PATCH 5/6] Sites API: trim the two-step getter docblock Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018e9mXu6SCNbHMu1JhySDRG --- projects/plugins/jetpack/sal/class.json-api-site-base.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-base.php b/projects/plugins/jetpack/sal/class.json-api-site-base.php index ad22814e398d..13e94cf10358 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-base.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-base.php @@ -1900,8 +1900,7 @@ public function get_jetpack_recovery_mode_status() { * * The `jetpack_sso_require_two_step` option is the "Require two-step authentication" * checkbox in the SSO settings. The filter of the same name lets code override it, so - * this returns the same value checked by the SSO module. The requirement is only - * enforced while the module is active. + * this returns the same value checked by the SSO module. * * @return bool */ From ece5bbe1e76ebe45231137290245d8bc9df3ad32 Mon Sep 17 00:00:00 2001 From: Leonardo Sameshima Taba Date: Mon, 21 Sep 2026 18:50:23 -0300 Subject: [PATCH 6/6] Sites API: one-line docblock for the two-step getter Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018e9mXu6SCNbHMu1JhySDRG --- projects/plugins/jetpack/sal/class.json-api-site-base.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-base.php b/projects/plugins/jetpack/sal/class.json-api-site-base.php index 13e94cf10358..ad0b64730945 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-base.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-base.php @@ -1898,10 +1898,6 @@ public function get_jetpack_recovery_mode_status() { /** * Whether WordPress.com accounts must have two-step authentication to log in through SSO. * - * The `jetpack_sso_require_two_step` option is the "Require two-step authentication" - * checkbox in the SSO settings. The filter of the same name lets code override it, so - * this returns the same value checked by the SSO module. - * * @return bool */ public function get_jetpack_sso_require_two_step() {