Skip to content

Commit 8650b05

Browse files
authored
Merge pull request #3615 from dparker1005/codex/stripe-webhook-ajax-auth
Add auth and nonce checks to Stripe webhook AJAX handlers
2 parents ab247f0 + 12bfa31 commit 8650b05

3 files changed

Lines changed: 59 additions & 0 deletions

File tree

classes/gateways/class.pmprogateway_stripe.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,10 +1095,57 @@ public static function save_settings_fields() {
10951095
}
10961096
}
10971097

1098+
/**
1099+
* Validate access to Stripe webhook AJAX handlers.
1100+
*
1101+
* @since 3.2.6
1102+
*
1103+
* @param bool $silent Whether to return errors instead of exiting.
1104+
* @return true|array
1105+
*/
1106+
private static function authorize_stripe_webhook_request( $silent = false ) {
1107+
if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'pmpro_paymentsettings' ) ) {
1108+
$r = array(
1109+
'success' => false,
1110+
'notice' => 'error',
1111+
'message' => esc_html__( 'You do not have permission to perform this action.', 'paid-memberships-pro' ),
1112+
);
1113+
1114+
if ( $silent ) {
1115+
return $r;
1116+
}
1117+
1118+
echo wp_json_encode( $r ); // Values escaped above.
1119+
exit;
1120+
}
1121+
1122+
if ( wp_doing_ajax() && false === check_ajax_referer( 'pmpro_stripe_webhook_nonce', 'nonce', false ) ) {
1123+
$r = array(
1124+
'success' => false,
1125+
'notice' => 'error',
1126+
'message' => esc_html__( 'Your session has expired. Please refresh and try again.', 'paid-memberships-pro' ),
1127+
);
1128+
1129+
if ( $silent ) {
1130+
return $r;
1131+
}
1132+
1133+
echo wp_json_encode( $r ); // Values escaped above.
1134+
exit;
1135+
}
1136+
1137+
return true;
1138+
}
1139+
10981140
/**
10991141
* AJAX callback to create webhooks.
11001142
*/
11011143
public static function wp_ajax_pmpro_stripe_create_webhook( $silent = false ) {
1144+
$access_check = self::authorize_stripe_webhook_request( $silent );
1145+
if ( true !== $access_check ) {
1146+
return $access_check;
1147+
}
1148+
11021149
$stripe = new PMProGateway_stripe();
11031150
$update_webhook_response = $stripe->update_webhook_events();
11041151

@@ -1129,6 +1176,11 @@ public static function wp_ajax_pmpro_stripe_create_webhook( $silent = false ) {
11291176
* AJAX callback to disable webhooks.
11301177
*/
11311178
public static function wp_ajax_pmpro_stripe_delete_webhook( $silent = false ) {
1179+
$access_check = self::authorize_stripe_webhook_request( $silent );
1180+
if ( true !== $access_check ) {
1181+
return $access_check;
1182+
}
1183+
11321184
$stripe = new PMProGateway_stripe();
11331185
$webhook = $stripe->does_webhook_exist();
11341186

@@ -1162,6 +1214,9 @@ public static function wp_ajax_pmpro_stripe_delete_webhook( $silent = false ) {
11621214
* AJAX callback to rebuild webhook.
11631215
*/
11641216
public static function wp_ajax_pmpro_stripe_rebuild_webhook() {
1217+
// This handler always sends its own response, so we do not need silent auth handling here.
1218+
self::authorize_stripe_webhook_request();
1219+
11651220
// First try to delete the webhook.
11661221
$r = self::wp_ajax_pmpro_stripe_delete_webhook( true ) ;
11671222
if ( $r['success'] ) {

includes/scripts.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ function pmpro_admin_enqueue_scripts() {
156156
'all_levels_formatted_text' => $all_levels_formatted_text,
157157
'all_level_values_and_labels' => $all_level_values_and_labels,
158158
'checkout_url' => pmpro_url( 'checkout' ),
159+
'stripe_webhook_nonce' => wp_create_nonce( 'pmpro_stripe_webhook_nonce' ),
159160
'user_fields_blank_group' => $empty_field_group_html,
160161
'user_fields_blank_field' => $empty_field_html,
161162
// We want the core WP translation so we can check for it in JS.

js/pmpro-admin.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ jQuery(document).ready(function () {
148148

149149
var postData = {
150150
action: 'pmpro_stripe_create_webhook',
151+
nonce: pmpro.stripe_webhook_nonce,
151152
secretkey: pmpro_stripe_get_secretkey(),
152153
}
153154
jQuery.ajax({
@@ -180,6 +181,7 @@ jQuery(document).ready(function () {
180181

181182
var postData = {
182183
action: 'pmpro_stripe_delete_webhook',
184+
nonce: pmpro.stripe_webhook_nonce,
183185
secretkey: pmpro_stripe_get_secretkey(),
184186
}
185187

@@ -213,6 +215,7 @@ jQuery(document).ready(function () {
213215

214216
var postData = {
215217
action: 'pmpro_stripe_rebuild_webhook',
218+
nonce: pmpro.stripe_webhook_nonce,
216219
secretkey: pmpro_stripe_get_secretkey(),
217220
}
218221

0 commit comments

Comments
 (0)