| @@ -240,15 +240,16 @@ | ||
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | - // Save valid results when they are being triggered from an ajax request | |
| 245 | - if( wp_doing_ajax() && isset( $_POST['action'] ) && $_POST['action'] == 'pms_validate_checkout' ){ | |
| 244 | + // Save valid results when they are being triggered from an ajax request that only pre-validates the | |
| 245 | + // credentials, so the same single use token is still accepted on the form submission that follows it | |
| 246 | + if( wppb_is_captcha_prevalidation_request() ){ | |
| 246 | 247 | |
| 247 | - $saved = get_option( 'wppb_turnstile_validations', array() ); | |
| 248 | + $saved = wppb_prune_captcha_prevalidations( get_option( 'wppb_turnstile_validations', array() ) ); | |
| 248 | 249 | |
| 249 | 250 | if( $already_validated === true ) |
| 250 | - $saved[ $turnstile_response_field ] = true; | |
| 251 | + $saved[ $turnstile_response_field ] = time(); | |
| 251 | 252 | |
| 252 | 253 | update_option( 'wppb_turnstile_validations', $saved, false ); |
| 253 | 254 | |
| 254 | 255 | } |
| @@ -481,34 +482,34 @@ | ||
| 481 | 482 | if ( isset( $_POST['log'] ) && !is_wp_error($user) && !isset( $_POST['pms_login'] ) ) { |
| 482 | 483 | |
| 483 | 484 | $field = wppb_get_turnstile_field(); |
| 484 | 485 | if ( !empty($field) ){ |
| 485 | - global $wppb_turnstile_response; | |
| 486 | + /* Work out whether Turnstile is enabled for the form that was actually submitted before verifying | |
| 487 | + anything. The Cloudflare token is single use, so verifying it on a form where our widget was never | |
| 488 | + displayed spends a token that belongs to whatever else protects that form, and that plugin\'s own | |
| 489 | + check then fails with timeout-or-duplicate. */ | |
| 490 | + if ( isset($_POST['wppb_login']) && ($_POST['wppb_login'] == true) ) { | |
| 491 | + // it\'s a PB login form, check if we have Turnstile on it | |
| 492 | + $turnstile_enabled = ( isset($field['turnstile-pb-forms']) && (strpos($field['turnstile-pb-forms'], 'pb_login') !== false) ); | |
| 493 | + } | |
| 494 | + else { | |
| 495 | + // default WP login form | |
| 496 | + $turnstile_enabled = ( isset($field['turnstile-wp-forms']) && (strpos($field['turnstile-wp-forms'], 'default_wp_login') !== false) ); | |
| 497 | + } | |
| 486 | 498 | |
| 487 | - if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) ); | |
| 499 | + if ( $turnstile_enabled ) { | |
| 500 | + global $wppb_turnstile_response; | |
| 488 | 501 | |
| 489 | - $turnstile_error_message = __('Cloudflare Turnstile could not be verified. Please try again.','profile-builder'); | |
| 502 | + if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) ); | |
| 490 | 503 | |
| 491 | - //Turnstile error for displaying on the PB login form | |
| 492 | - if ( isset($_POST['wppb_login']) && ($_POST['wppb_login'] == true) ) { | |
| 504 | + $turnstile_error_message = __('Cloudflare Turnstile could not be verified. Please try again.','profile-builder'); | |
| 493 | 505 | |
| 494 | - // it\'s a PB login form, check if we have Turnstile on it and display error if not valid | |
| 495 | - if ((isset($field['turnstile-pb-forms'])) && (strpos($field['turnstile-pb-forms'], 'pb_login') !== false) && ($wppb_turnstile_response == false)) { | |
| 506 | + if ( $wppb_turnstile_response == false ) { | |
| 496 | 507 | $user = new WP_Error('wppb_turnstile_error', $turnstile_error_message); |
| 497 | 508 | remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 ); |
| 498 | 509 | remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 ); |
| 499 | 510 | } |
| 500 | - | |
| 501 | 511 | } |
| 502 | - else { | |
| 503 | - //Turnstile error for displaying on the default WP login form | |
| 504 | - if (isset($field['turnstile-wp-forms']) && (strpos($field['turnstile-wp-forms'], 'default_wp_login') !== false) && ($wppb_turnstile_response == false)) { | |
| 505 | - $user = new WP_Error('wppb_turnstile_error', $turnstile_error_message); | |
| 506 | - remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 ); | |
| 507 | - remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 ); | |
| 508 | - } | |
| 509 | - | |
| 510 | - } | |
| 511 | 512 | } |
| 512 | 513 | } |
| 513 | 514 | return $user; |
| 514 | 515 | } |
| @@ -563,18 +564,21 @@ | ||
| 563 | 564 | return; |
| 564 | 565 | |
| 565 | 566 | $field = wppb_get_turnstile_field(); |
| 566 | 567 | if ( !empty($field) ){ |
| 567 | - global $wppb_turnstile_response; | |
| 568 | - if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) ); | |
| 568 | + /* Only verify where Turnstile is configured for the form being submitted. The Cloudflare token is | |
| 569 | + single use, so verifying it on a form our widget was never displayed on spends a token that another | |
| 570 | + plugin protecting that form still needs, and its own check then fails with timeout-or-duplicate. */ | |
| 571 | + if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_recover_password' ) !== false ) ) { | |
| 572 | + global $wppb_turnstile_response; | |
| 573 | + if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) ); | |
| 569 | 574 | |
| 570 | - $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder'); | |
| 575 | + $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder'); | |
| 571 | 576 | |
| 572 | - // Fail closed, but only where Turnstile is configured for this form. Gate on turnstile-wp-forms (as the | |
| 573 | - // login path does) instead of isset() of the token, so a missing token is treated as a failed verification | |
| 574 | - // without blocking default WP password recovery on sites that only use Turnstile on PB forms. | |
| 575 | - if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_recover_password' ) !== false ) && ( $wppb_turnstile_response == false ) ) { | |
| 576 | - wp_die( esc_html( $turnstile_error_message ) . '<br />' . esc_html__( "Click the BACK button on your browser, and try again.", 'profile-builder' ) ) ; | |
| 577 | + // Fail closed: a missing token is treated as a failed verification. | |
| 578 | + if ( $wppb_turnstile_response == false ) { | |
| 579 | + wp_die( esc_html( $turnstile_error_message ) . '<br />' . esc_html__( "Click the BACK button on your browser, and try again.", 'profile-builder' ) ) ; | |
| 580 | + } | |
| 577 | 581 | } |
| 578 | 582 | } |
| 579 | 583 | } |
| 580 | 584 | add_action('lostpassword_post','wppb_verify_turnstile_default_wp_recover_password'); |
| @@ -610,18 +614,21 @@ | ||
| 610 | 614 | function wppb_verify_turnstile_default_wp_register( $errors ){ |
| 611 | 615 | |
| 612 | 616 | $field = wppb_get_turnstile_field(); |
| 613 | 617 | if ( !empty($field) ){ |
| 614 | - global $wppb_turnstile_response; | |
| 615 | - if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) ); | |
| 618 | + /* Only verify where Turnstile is configured for the form being submitted. The Cloudflare token is | |
| 619 | + single use, so verifying it on a form our widget was never displayed on spends a token that another | |
| 620 | + plugin protecting that form still needs, and its own check then fails with timeout-or-duplicate. */ | |
| 621 | + if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_register' ) !== false ) ) { | |
| 622 | + global $wppb_turnstile_response; | |
| 623 | + if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) ); | |
| 616 | 624 | |
| 617 | - $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder'); | |
| 625 | + $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder'); | |
| 618 | 626 | |
| 619 | - // Fail closed, but only where Turnstile is configured for this form. Gate on turnstile-wp-forms (as the | |
| 620 | - // login path does) instead of isset() of the token, so a missing token is treated as a failed verification | |
| 621 | - // without blocking default WP registration on sites that only use Turnstile on PB forms. | |
| 622 | - if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_register' ) !== false ) && ( $wppb_turnstile_response == false ) ) { | |
| 623 | - $errors->add( 'wppb_turnstile_error', $turnstile_error_message ); | |
| 627 | + // Fail closed: a missing token is treated as a failed verification. | |
| 628 | + if ( $wppb_turnstile_response == false ) { | |
| 629 | + $errors->add( 'wppb_turnstile_error', $turnstile_error_message ); | |
| 630 | + } | |
| 624 | 631 | } |
| 625 | 632 | } |
| 626 | 633 | |
| 627 | 634 | return $errors; |