Skip to content

Commit

Permalink
Merge pull request #3213 from WordImpress/issue/3200
Browse files Browse the repository at this point in the history
fix(donations): resolve often reported "Error: Nonce verification has failed." #3200
  • Loading branch information
Devin Walker committed May 16, 2018
2 parents 7df071e + abda0b0 commit ffae246
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 240 deletions.
18 changes: 18 additions & 0 deletions assets/src/js/frontend/give-ajax.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ jQuery( document ).ready( function( $ ) {
//Hide loading elements
$( '.give-loading-text' ).hide();

// Update and invalidate cached nonce.
$('.give-form').each(function (index, $form) {
$form = jQuery($form);

const $nonceField = jQuery('input[name="give-form-hash"]', $form),
nonceTime = parseInt($nonceField.data('time')) + parseInt($nonceField.data('nonce-life')),
currentTime = Math.round(Date.now() / 1000);

let timeDiff = nonceTime - currentTime;

timeDiff = 0 > timeDiff ? timeDiff : (timeDiff + 100);

// Update nonce in background.
window.setTimeout(function () {
Give.form.fn.resetNonce($form);
}, timeDiff);
});

// Show the login form in the checkout when the user clicks the "Login" link
$( document ).on( 'click', '.give-checkout-login', function( e ) {
var $this = $( this );
Expand Down
8 changes: 6 additions & 2 deletions assets/src/js/frontend/give-donations.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ Give.form = {

switch ( type ) {
case 'nonce':
$form.find( 'input[name="_wpnonce"]' ).val( val );
$form.find( 'input[name="give-form-hash"]' ).val( val );
break;
}

Expand Down Expand Up @@ -569,7 +569,7 @@ Give.form = {
return '';
}

var nonce = $form.find( 'input[name="_wpnonce"]' ).val();
let nonce = $form.find( 'input[name="give-form-hash"]' ).val();

if ( 'undefined' === typeof nonce || ! nonce ) {
nonce = '';
Expand All @@ -592,6 +592,8 @@ Give.form = {
return false;
}

Give.form.fn.disable( $form, true );

//Post via AJAX to Give
jQuery.post( give_global_vars.ajaxurl, {
action: 'give_donation_form_nonce',
Expand All @@ -600,6 +602,8 @@ Give.form = {
function( response ) {
// Update nonce field.
Give.form.fn.setInfo( 'nonce', response.data, $form, '' );

Give.form.fn.disable( $form, false );
}
);
},
Expand Down
18 changes: 8 additions & 10 deletions includes/formatting.php
Original file line number Diff line number Diff line change
Expand Up @@ -656,9 +656,9 @@ function give_let_to_num( $size ) {
*
* @since 1.8
*
* @param $nonce
* @param int $action
* @param array $wp_die_args
* @param string $nonce Nonce Hash.
* @param int $action Nonce verification action.
* @param array $wp_die_args Nonce fail arguments.
*
* @return bool
*/
Expand All @@ -680,7 +680,7 @@ function give_validate_nonce( $nonce, $action = - 1, $wp_die_args = array() ) {
'title' => __( 'Error', 'give' ),
'args' => array(
'response' => 403,
)
),
)
);

Expand All @@ -699,17 +699,15 @@ function give_validate_nonce( $nonce, $action = - 1, $wp_die_args = array() ) {
*
* @since 2.0
*
* @param string $nonce Pass nonce value.
* @param string $nonce Nonce value.
* @param int $form_id Donation Form ID.
*
* @return bool
*/
function give_verify_donation_form_nonce( $nonce = '' ) {
// Get nonce key from donation.
$nonce = empty( $nonce ) ? give_clean( $_POST['_wpnonce'] ) : $nonce;
$form_id = isset( $_POST['give-form-id'] ) ? absint( $_POST['give-form-id'] ) : 0;
function give_verify_donation_form_nonce( $nonce = '', $form_id ) {

// Form nonce action.
$nonce_action = "donation_form_nonce_{$form_id}";
$nonce_action = "give_donation_form_nonce_{$form_id}";

// Nonce validation.
$verify_nonce = give_validate_nonce( $nonce, $nonce_action );
Expand Down
23 changes: 14 additions & 9 deletions includes/forms/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ function give_get_donation_form( $args = array() ) {
*/
do_action( 'give_pre_form', $form->ID, $args, $form );


// Set form html tags.
$form_html_tags = array(
'id' => "give-form-{$args['id_prefix']}",
Expand Down Expand Up @@ -1174,6 +1173,7 @@ function give_get_register_fields( $form_id ) {
?>
<?php _e( 'Create an account', 'give' ); ?>
<?php echo Give()->tooltips->render_help( __( 'Create an account on the site to see and manage donation history.', 'give' ) ); ?>
<?php wp_nonce_field( 'give_form_create_user_nonce', 'give-form-user-register-hash', false, true );?>
</label>
</div>

Expand Down Expand Up @@ -1959,12 +1959,11 @@ function give_members_only_form( $final_output, $args ) {
function __give_form_add_donation_hidden_field( $form_id, $args, $form ) {
$id_prefix = ! empty( $args['id_prefix'] ) ? $args['id_prefix'] : '';
?>
<input type="hidden" name="give-form-id" value="<?php echo $form_id; ?>"/>
<input type="hidden" name="give-form-title" value="<?php echo htmlentities( $form->post_title ); ?>"/>
<input type="hidden" name="give-current-url"
value="<?php echo htmlspecialchars( give_get_current_page_url() ); ?>"/>
<input type="hidden" name="give-form-url" value="<?php echo htmlspecialchars( give_get_current_page_url() ); ?>"/>
<input type="hidden" name="give-form-id-prefix" value="<?php echo $id_prefix; ?>"/>
<input type="hidden" name="give-form-id" value="<?php echo intval( $form_id ); ?>"/>
<input type="hidden" name="give-form-title" value="<?php echo esc_html( $form->post_title ); ?>"/>
<input type="hidden" name="give-current-url" value="<?php echo esc_url( give_get_current_page_url() ); ?>"/>
<input type="hidden" name="give-form-url" value="<?php echo esc_url( give_get_current_page_url() ); ?>"/>
<?php
// Get the custom option amount.
$custom_amount = give_get_meta( $form_id, '_give_custom_amount', true );
Expand All @@ -1980,14 +1979,20 @@ function __give_form_add_donation_hidden_field( $form_id, $args, $form ) {
}

// WP nonce field.
wp_nonce_field( "donation_form_nonce_{$form_id}", '_wpnonce', false );
echo str_replace(
'/>',
'data-time="' . time() . '" data-nonce-life="' . give_get_nonce_life() . '"/>',
give_get_nonce_field( "give_donation_form_nonce_{$form_id}", 'give-form-hash', false )
);

// Price ID hidden field for variable (multi-level) donation forms.
if ( give_has_variable_prices( $form_id ) ) {

// Get default selected price ID.
$prices = apply_filters( 'give_form_variable_prices', give_get_variable_prices( $form_id ), $form_id );
$price_id = 0;
//loop through prices.

// Loop through prices.
foreach ( $prices as $price ) {
if ( isset( $price['_give_default'] ) && $price['_give_default'] === 'default' ) {
$price_id = $price['_give_id']['level_id'];
Expand Down Expand Up @@ -2132,4 +2137,4 @@ function give_redirect_and_popup_form( $redirect, $args ) {
return $redirect;
}

add_filter( 'give_send_back_to_checkout', 'give_redirect_and_popup_form', 10, 2 );
add_filter( 'give_send_back_to_checkout', 'give_redirect_and_popup_form', 10, 2 );
6 changes: 4 additions & 2 deletions includes/gateways/actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ function give_process_gateway_select( $data ) {
*/
function give_load_ajax_gateway() {

$post_data = give_clean( $_POST ); // WPCS: input var ok.
$post_data = give_clean( $_POST ); // WPCS: input var ok, CSRF ok.

if ( isset( $post_data['give_payment_mode'] ) ) {

$form_id_prefix = ! empty( $post_data['give_form_id_prefix'] ) ? $post_data['give_form_id_prefix'] : '';

$args = array(
'id_prefix' => $post_data['give_form_id_prefix'],
'id_prefix' => $form_id_prefix,
);

/**
Expand Down
38 changes: 37 additions & 1 deletion includes/misc-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1928,4 +1928,40 @@ function __give_get_active_by_user_meta( $banner_addon_name ) {
}

return $data;
}
}


/**
* Get time interval for which nonce is valid
*
* @since 2.1.3
*
* @return int
*/
function give_get_nonce_life(){
/**
* Filters the lifespan of nonces in seconds.
*
* @see wp-inlucdes/pluggable.php:wp_nonce_tick
*/
return (int) apply_filters( 'nonce_life', DAY_IN_SECONDS );
}

/**
* Get nonce field without id
*
* @since 2.1.3
*
* @param string $action
* @param string $name
* @param bool $referer
*
* @return string
*/
function give_get_nonce_field( $action, $name, $referer = false ) {
return str_replace(
"id=\"{$name}\"",
'',
wp_nonce_field( $action, $name, $referer, false )
);
}

0 comments on commit ffae246

Please sign in to comment.