PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 1.2.0
WP 2FA – Two-factor authentication for WordPress v1.2.0
1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / UserProfile.php
wp-2fa / includes / classes / Admin Last commit date
SettingsPage.php 6 years ago SetupWizard.php 6 years ago UserNotices.php 6 years ago UserProfile.php 6 years ago UserRegistered.php 6 years ago
UserProfile.php
944 lines
1 <?php // phpcs:ignore
2
3 namespace WP2FA\Admin;
4
5 use \WP2FA\Authenticator\Authentication as Authentication;
6 use \WP2FA\WP2FA as WP2FA;
7 use \WP2FA\Core as Core;
8 use \WP2FA\Authenticator\BackupCodes as BackupCodes;
9
10 /**
11 * UserProfile - Class for handling user things such as profile settings and admin list views.
12 */
13 class UserProfile {
14
15 const NOTICES_META_KEY = 'wp_2fa_totp_notices';
16
17 /**
18 * Classs constructor
19 */
20 public function __construct() {
21 }
22
23 /**
24 * Add our buttons to the user profile editing screen.
25 *
26 * @param object $user User data.
27 */
28 public function user_2fa_options( $user ) {
29
30 if ( isset( $_GET['user_id'] ) ) {
31 $user_id = (int) $_GET['user_id'];
32 $user = get_user_by( 'id', $user_id );
33 } else {
34 $user = wp_get_current_user();
35 }
36
37 // Get current user, we going to need this regardless.
38 $current_user = wp_get_current_user();
39
40 // Bail if we still dont have an object.
41 if ( ! is_a( $user, '\WP_User' ) || ! is_a( $current_user, '\WP_User' ) ) {
42 return;
43 }
44
45 $roles = (array) $user->roles;
46
47 // Grab grace period UNIX time.
48 $grace_period_expired = get_user_meta( $user->ID, 'wp_2fa_user_grace_period_expired', true );
49 // Grab current time, we going to compare these later.
50 $time_now = time();
51 $is_user_excluded = WP2FA::is_user_excluded( $user->ID );
52
53 // First lets see if the user already has a token.
54 $enabled_methods = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true );
55
56 if ( ! $grace_period_expired && $current_user->ID === $user->ID && ! $is_user_excluded && ! empty( $roles ) ) {
57
58 // These are the buttons we show if a user has no enabled methods.
59 if ( ! empty( $enabled_methods && $user->ID === $current_user->ID ) ) {
60 // Create wizard link based on which 2fa methods are allowed by admin.
61 if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) && ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) {
62 if ( WP2FA::is_this_multisite() ) {
63 $button_link = admin_url( 'index.php?page=wp-2fa-setup&current-step=user_choose_2fa_method&wizard_type=user_2fa_config' );
64 } else {
65 $button_link = admin_url( 'options-general.php?page=wp-2fa-setup&current-step=user_choose_2fa_method&wizard_type=user_2fa_config' );
66 }
67
68 } else {
69 if ( WP2FA::is_this_multisite() ) {
70 $button_link = admin_url( 'index.php?page=wp-2fa-setup&current-step=reconfigure_method&wizard_type=user_reconfigure_config' );
71 } else {
72 $button_link = admin_url( 'options-general.php?page=wp-2fa-setup&current-step=reconfigure_method&wizard_type=user_reconfigure_config' );
73 }
74 }
75 // Create remove 2fa link.
76 $url = add_query_arg(
77 array(
78 'action' => 'remove_user_2fa',
79 'user_id' => $user->ID,
80 'wp_2fa_nonce' => wp_create_nonce( 'wp-2fa-remove-user-2fa-nonce' ),
81 ),
82 admin_url( 'user-edit.php' )
83 );
84 if ( WP2FA::is_this_multisite() ) {
85 $backup_codes_link = admin_url( 'index.php?page=wp-2fa-setup&current-step=backup_codes&wizard_type=backup_codes_config' );
86 } else {
87 $backup_codes_link = admin_url( 'options-general.php?page=wp-2fa-setup&current-step=backup_codes&wizard_type=backup_codes_config' );
88 }
89 ?>
90 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
91 <p class="description"><?php esc_html_e( 'Add two-factor authentication to strengthen the security of your WordPress user account.', 'wp-2fa' ); ?></p>
92 <table class="form-table" role="presentation">
93 <tbody>
94 <tr>
95 <th><label><?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?></label></th>
96 <td>
97 <a href="<?php echo esc_url( $button_link ); ?>" class="button button-primary"><?php esc_html_e( 'Change 2FA Settings', 'wp-2fa' ); ?></a> <a href="#" class="button button-primary remove-2fa" onclick="MicroModal.show('confirm-remove-2fa');"><?php esc_html_e( 'Remove 2FA', 'wp-2fa' ); ?></a>
98 <br />
99 <br />
100 <a href="<?php echo esc_url( $backup_codes_link ); ?>" class="button button-primary"><?php esc_html_e( 'Generate backup codes', 'wp-2fa' ); ?></a>
101 <?php
102 $codes_remaining = BackupCodes::codes_remaining_for_user( $user );
103 if ( $codes_remaining > 0 ) {
104 ?>
105 <span class="description mt-5px"><?php echo esc_attr( (int) $codes_remaining ); ?> <?php esc_html_e( 'unused backup codes remaining.', 'wp-2fa' ); ?></span>
106 <?php
107 } elseif ( 0 === $codes_remaining ) {
108 ?>
109 <a class="learn_more_link" href="https://www.wpwhitesecurity.com/2fa-backup-codes/?utm_source=plugin&utm_medium=referral&utm_campaign=wp2fa&utm_content=settings+pages" target="_blank"><?php esc_html_e( 'Learn more.', 'wp-2fa' ); ?></a>
110 <?php
111 }
112 ?>
113 </td>
114 </tr>
115 </tbody>
116 </table>
117 <div class="wp2fa-modal micromodal-slide" id="confirm-remove-2fa" aria-hidden="true">
118 <div class="modal__overlay" tabindex="-1" data-micromodal-close>
119 <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
120 <header class="modal__header">
121 <h2 class="modal__title" id="modal-1-title">
122 <?php esc_html_e( 'Remove 2FA?', 'wp-2fa' ); ?>
123 </h2>
124 <button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
125 </header>
126 <main class="modal__content" id="modal-1-content">
127 <p>
128 <?php esc_html_e( 'Are you sure you want to remove two-factor authentication and lower the security of your user account?', 'wp-2fa' ); ?>
129 </p>
130 </main>
131 <footer class="modal__footer">
132 <a href="<?php echo esc_url( $url ); ?>" class="modal__btn modal__btn-primary" data-trigger-remove-2fa><?php esc_html_e( 'Yes', 'wp-2fa' ); ?></a>
133 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'No', 'wp-2fa' ); ?></button>
134 </footer>
135 </div>
136 </div>
137 </div>
138
139 <?php
140 } else {
141
142 if ( WP2FA::is_this_multisite() ) {
143 $first_time_setup_link = admin_url( 'index.php?page=wp-2fa-setup&current-step=choose_2fa_method&first_time_setup=true' );
144 } else {
145 $first_time_setup_link = admin_url( 'options-general.php?page=wp-2fa-setup&current-step=choose_2fa_method&first_time_setup=true' );
146 }
147 ?>
148 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
149 <p class="description"><?php esc_html_e( 'Add two-factor authentication to strengthen the security of your WordPress user account.', 'wp-2fa' ); ?></p>
150 <table class="form-table" role="presentation">
151 <tbody>
152 <tr>
153 <th><label><?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?></label></th>
154 <td>
155 <a href="<?php echo esc_url( $first_time_setup_link ); ?>" class="button button-primary"><?php esc_html_e( 'Configure Two-factor authentication (2FA)', 'wp-2fa' ); ?></a>
156 </td>
157 </tr>
158 </tbody>
159 </table>
160 <?php
161 }
162 } elseif ( $is_user_excluded ) {
163 ?>
164 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
165 <p class="description"><?php esc_html_e( 'Add two-factor authentication to strengthen the security of your WordPress user account.', 'wp-2fa' ); ?></p>
166 <p class="description"><?php esc_html_e( 'Your user / role is not permitted to configure 2FA. Contact your administrator for more information.', 'wp-2fa' ); ?></p>
167 <?php
168 } elseif ( $grace_period_expired && current_user_can( 'manage_options' ) ) {
169 ?>
170 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
171 <table class="form-table" role="presentation">
172 <tbody>
173 <tr>
174 <th><label><?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?></label></th>
175 <td>
176 <?php
177 $url = add_query_arg(
178 array(
179 'action' => 'unlock_account',
180 'user_id' => $user->ID,
181 'wp_2fa_nonce' => wp_create_nonce( 'wp-2fa-unlock-account-nonce' ),
182 ),
183 admin_url( 'user-edit.php' )
184 );
185
186 if ( $grace_period_expired ) {
187 ?>
188 <a href="<?php echo esc_url( $url ); ?>" class="button button-primary"><?php esc_html_e( 'Unlock user and reset the grace period', 'wp-2fa' ); ?></a>
189 <?php
190 }
191 ?>
192 </td>
193 </tr>
194 </tbody>
195 </table>
196 <?php
197 } elseif ( ! $grace_period_expired && current_user_can( 'manage_options' ) && ! empty( $enabled_methods ) ) {
198 ?>
199 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
200 <p class="description"><?php esc_html_e( 'By resetting this user\'s 2FA configuration you disable the currently configured 2FA so the user can log back in using a usemame and a password only. *the user if enforced to setup 2FA the user will get a prompt upon logging in, from where 2FA can be configured. The user has to configure 2FA within the configured grace period.', 'wp-2fa' ); ?></p>
201 <table class="form-table" role="presentation">
202 <tbody>
203 <tr>
204 <th><label><?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?></label></th>
205 <td>
206 <?php
207 // Create remove 2fa link.
208 $url = add_query_arg(
209 array(
210 'action' => 'remove_user_2fa',
211 'user_id' => $user->ID,
212 'wp_2fa_nonce' => wp_create_nonce( 'wp-2fa-remove-user-2fa-nonce' ),
213 'admin_reset' => 'yes',
214 ),
215 admin_url( 'user-edit.php' )
216 );
217 ?>
218 <a href="<?php echo esc_url( $url ); ?>" class="button button-primary"><?php esc_html_e( 'Reset 2FA configuration', 'wp-2fa' ); ?></a>
219 </td>
220 </tr>
221 </tbody>
222 </table>
223 <?php
224 } elseif ( empty( $roles ) ) {
225 echo $this->inline_2fa_profile_form();
226 }
227
228 }
229
230 /**
231 * Produces the 2FA configuration form for network users, or any user with no roles.
232 */
233 public function inline_2fa_profile_form() {
234 if ( isset( $_GET['user_id'] ) ) {
235 $user_id = (int) $_GET['user_id'];
236 $user = get_user_by( 'id', $user_id );
237 } else {
238 $user = wp_get_current_user();
239 }
240
241 // Get current user, we going to need this regardless.
242 $current_user = wp_get_current_user();
243
244 // Bail if we still dont have an object.
245 if ( ! is_a( $user, '\WP_User' ) || ! is_a( $current_user, '\WP_User' ) ) {
246 return;
247 }
248
249 // Grab grace period UNIX time.
250 $grace_period_expired = get_user_meta( $user->ID, 'wp_2fa_grace_period_expiry', true );
251
252 // Grab current time, we going to compare these later.
253 $time_now = time();
254 $is_user_excluded = WP2FA::is_user_excluded( $user->ID );
255 $enabled_methods = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true );
256 $is_needed = Authentication::is_user_eligible_for_2fa( $user->ID );
257
258 // First lets see if the user already has a token.
259 $enabled_methods = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true );
260
261 if ( $is_needed && ! $is_user_excluded ) {
262
263 // Check if current user viewing the profile is the owner of the profile.
264 if ( isset( $_GET['user_id'] ) ) {
265 $user_id = (int) $_GET['user_id'];
266 $user = get_user_by( 'id', $user_id );
267 $curent_user = wp_get_current_user();
268 if ( $curent_user->ID !== $user->ID ) {
269 return;
270 }
271 }
272
273 // Show this to user who has enabled methods
274 if ( ! empty( $enabled_methods ) && $user->ID === $current_user->ID ) {?>
275
276 <h2>
277 <?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?>
278 </h2>
279 <p class="description">
280 <?php esc_html_e( 'Add two-factor authentication to strengthen the security of your WordPress user account.', 'wp-2fa' ); ?>
281 </p>
282 <table class="form-table" role="presentation">
283 <tbody>
284 <tr>
285 <th>
286 <label>
287 <?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?>
288 </label>
289 </th>
290 <td>
291 <a href="#" class="button button-primary remove-2fa" onclick="MicroModal.show('configure-2fa',{
292 onShow: modal => jQuery( '.wizard-step:first-of-type' ).addClass( 'active' ),
293 onClose: modal => jQuery( '.wizard-step.active' ).removeClass( 'active' ),
294 });"><?php esc_html_e( 'Change 2FA Settings', 'wp-2fa' ); ?></a>
295
296 <a href="#" class="button button-primary remove-2fa" onclick="MicroModal.show('configure-2fa-backup-codes',{
297 onShow: modal => jQuery( '.wizard-step:first-of-type' ).addClass( 'active' ),
298 onClose: modal => jQuery( '.wizard-step.active' ).removeClass( 'active' ),
299 });"><?php esc_html_e( 'Generate Backup Codes', 'wp-2fa' ); ?></a>
300
301 <?php
302 $codes_remaining = BackupCodes::codes_remaining_for_user( $user );
303 if ( $codes_remaining > 0 ) {
304 ?>
305 <span class="description mt-5px"><?php echo esc_attr( (int) $codes_remaining ); ?> <?php esc_html_e( 'unused backup codes remaining.', 'wp-2fa' ); ?></span>
306 <?php
307 } elseif ( 0 === $codes_remaining ) {
308 ?>
309 <a class="learn_more_link" href="https://www.wpwhitesecurity.com/2fa-backup-codes/?utm_source=plugin&utm_medium=referral&utm_campaign=wp2fa&utm_content=settings+pages" target="_blank"><?php esc_html_e( 'Learn more.', 'wp-2fa' ); ?></a>
310 <?php
311 }
312 ?>
313
314 <td>
315 <div class="wp2fa-modal micromodal-slide" id="configure-2fa" aria-hidden="true">
316 <div class="modal__overlay" tabindex="-1" data-micromodal-close>
317 <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
318 <header class="modal__header">
319 <button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
320 </header>
321 <main class="modal__content" id="modal-1-content">
322 <?php
323 // Grab current user
324 $user = wp_get_current_user();
325
326 // Grab key from user meta
327 $key = Authentication::get_user_totp_key( $user->ID );
328
329 // If no key is present, lets make one
330 if ( empty( $key ) ) {
331 $key = Authentication::generate_key();
332 $update = update_user_meta( $user->ID, 'wp_2fa_totp_key', $key );
333 }
334
335 // Setup site information, used when generating our QR code
336 $site_name = get_bloginfo( 'name', 'display' );
337 $totp_title = apply_filters( 'wp_2fa_totp_title', $site_name . ':' . $user->user_login, $user );
338
339 // Now lets grab the users enabled 2fa methods.
340 $selected_method = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true );
341
342 // Create a nonce incase we want to reset the key
343 $nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . $user->ID );
344 $validate_nonce = wp_create_nonce( 'wp-2fa-validate-authcode' );
345 ?>
346
347 <div class="wizard-step active">
348 <fieldset>
349 <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) ) { ?>
350 <div class="option-pill">
351 <h3>
352 <?php esc_html_e( 'Reconfigure the Google Authenticator 2FA', 'wp-2fa' ); ?>
353 </h3>
354 <p>
355 <?php esc_html_e( 'Click the below button to reconfigure the current 2FA method. Note that once reset reset you will have to re-scan the QR code on all devices you want this to work on because the previous codes will stop working.', 'wp-2fa' ); ?>
356 </p>
357 <div class="wp2fa-setup-actions">
358 <a href="#" class="button button-primary" name="next_step_setting_modal_wizard" data-trigger-reset-key="no-reload" data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( $user->ID ); ?>" data-next-step="2fa-wizard-totp"><?php esc_html_e( 'Reset Key', 'wp-2fa' ); ?></a>
359 </div>
360 </div>
361 <?php } ?>
362 <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) {
363 $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' );
364 ?>
365 <br>
366 <div class="option-pill">
367 <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3>
368 <p>
369 <?php esc_html_e( 'Please select the email address where the one-time code should be sent:', 'wp-2fa' ); ?>
370 </p>
371 <fieldset>
372 <label for="use_wp_email">
373 <span><?php esc_html_e( 'Type in below the new email address where you want to receive the 2FA one-time codes.', 'wp-2fa' ); ?></span>
374 <br><br>
375 <input type="email" name="custom-email-address" id="custom-email-address" class="input wide" value=""/>
376 </label>
377 </fieldset>
378 <div class="wp2fa-setup-actions">
379 <a class="button button-primary" name="next_step_setting_modal_wizard" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>" data-trigger-setup-email data-user-id="<?php echo esc_attr( $user->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>" data-next-step="2fa-wizard-email"><?php esc_html_e( 'Change email address', 'wp-2fa' ); ?></a>
380 </div>
381 </div>
382 <?php } ?>
383 </fieldset>
384 </div>
385
386 <div class="wizard-step" id="2fa-wizard-totp">
387 <fieldset>
388
389 <div class="step-setting-wrapper active">
390 <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3>
391 <div class="option-pill">
392 <ol>
393 <li><?php esc_html_e( 'Download the Google Authenticator app', 'wp-2fa' ); ?></li>
394 <li><?php esc_html_e( 'Click the plus sign (add new icon)', 'wp-2fa' ); ?></li>
395 <li><?php esc_html_e( 'Select \'Scan a barcode\'', 'wp-2fa' ); ?></li>
396 <li><?php esc_html_e( 'Scan the QR code to the right.', 'wp-2fa' ); ?></li>
397 </ol>
398 <p><?php esc_html_e( 'Otherwise, select Enter a provided key and type in the key below:', 'wp-2fa' ); ?></p>
399 <code><?php echo esc_html( $key ); ?></code>
400 </div>
401 <img style="right: 21px; position: absolute; top: 103px;" src="<?php echo esc_url( Authentication::get_google_qr_code( $totp_title, $key, $site_name ) ); ?>" id="wp-2fa-totp-qrcode" />
402 <br>
403 <div class="wp2fa-setup-actions">
404 <br>
405 <a class="button button-primary" name="next_step_setting"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></a>
406 </div>
407 </div>
408
409 <div class="step-setting-wrapper">
410 <h3><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h3>
411 <p><?php esc_html_e( 'Please type in the one-time code from your Google Authenticator app to finalize the setup.', 'wp-2fa' ); ?></p>
412 <br>
413 <fieldset>
414 <label for="2fa-totp-authcode">
415 <?php esc_html_e( 'Authentication Code:', 'wp-2fa' ); ?>
416 <input type="tel" name="wp-2fa-totp-authcode" id="wp-2fa-totp-authcode" class="input" value="" size="20" pattern="[0-9]*" />
417 </label>
418 <div class="verification-response"></div>
419 </fieldset>
420 <br>
421 <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" />
422
423 <a href="#" class="modal__btn modal__btn-primary button" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validate_nonce ); ?>"><?php esc_html_e( 'Validate & Save Configuration', 'wp-2fa' ); ?></a>
424 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
425 </div>
426
427 </fieldset>
428 </div>
429
430 <div class="wizard-step" id="2fa-wizard-email">
431 <fieldset>
432
433 <div class="step-setting-wrapper active">
434 <h4><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h4>
435 <p><?php esc_html_e( 'Please type in the one-time code sent to your email address to finalize the setup.', 'wp-2fa' ); ?></p>
436 <br>
437 <fieldset>
438 <label for="2fa-email-authcode">
439 <?php esc_html_e( 'Authentication Code:', 'wp-2fa' ); ?>
440 <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*" />
441 </label>
442 <div class="verification-response"></div>
443 </fieldset>
444
445 <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" />
446 </div>
447 <br>
448 <a href="#" class="modal__btn modal__btn-primary button" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validate_nonce ); ?>"><?php esc_html_e( 'Validate Code', 'wp-2fa' ); ?></a>
449 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
450 </fieldset>
451 </div>
452
453 <div class="wizard-step" id="2fa-wizard-setup-done">
454 <fieldset>
455
456 <h3><?php esc_html_e( 'Your website just got more secure!', 'wp-2fa' ); ?></h3>
457 <p><?php esc_html_e( 'Congratulations! You have enabled two-factor authentication for your user. You’ve just helped towards making this website more secure!', 'wp-2fa' ); ?></p>
458
459 <p><?php esc_html_e( 'You can exit this wizard now or continue to configure the plugin’s general settings. ', 'wp-2fa' ); ?></p>
460
461 <p class="description"><?php esc_html_e( 'Note: all the settings can be configured from the Settings > Two-factor Authentication entry of your WordPress menu.', 'wp-2fa' ); ?></p>
462
463 </fieldset>
464 <a href="#" class="modal__btn modal__btn-primary button" name="next_step_setting_modal_wizard" data-next-step><?php esc_html_e( 'Next Step', 'wp-2fa' ); ?></a>
465 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Close', 'wp-2fa' ); ?></button>
466 </div>
467 </main>
468 </div>
469 </div>
470 </div>
471
472 <div class="wp2fa-modal micromodal-slide" id="configure-2fa-backup-codes" aria-hidden="true">
473 <div class="modal__overlay" tabindex="-1" data-micromodal-close>
474 <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
475 <header class="modal__header">
476 <button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
477 </header>
478 <main class="modal__content" id="modal-1-content">
479 <?php
480 // Grab current user.
481 $user = wp_get_current_user();
482 // Create a nonce for use in ajax call to generate codes.
483 $nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . $user->ID );
484 ?>
485 <div class="step-setting-wrapper active">
486 <h3><?php esc_html_e( 'Generate backup codes', 'wp-2fa' ); ?></h3>
487 <p><?php esc_html_e( 'It is recommended to generate and print some backup codes in case you lose access to your primary 2FA method. ', 'wp-2fa' ); ?></p>
488
489 <div class="wp2fa-setup-actions">
490 <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Generate backup codes', 'wp-2fa' ); ?>" data-trigger-generate-backup-codes data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( $user->ID ); ?>">
491 <?php esc_html_e( 'Generate backup codes', 'wp-2fa' ); ?>
492 </button>
493 <a href="<?php echo esc_url( admin_url() ); ?>" class="button button-secondary" type="submit" name="save_step" value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>">
494 <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?>
495 </a>
496 </div>
497 </div>
498
499 <div class="step-setting-wrapper align-center">
500 <h3><?php esc_html_e( 'Backup codes generated', 'wp-2fa' ); ?></h3>
501 <p><?php esc_html_e( 'Here are your backup codes:', 'wp-2fa' ); ?></p>
502 <code id="backup-codes-wrapper"></code>
503 <div class="wp2fa-setup-actions">
504 <button class="button button-primary" type="submit" value="<?php esc_attr_e( 'Download', 'wp-2fa' ); ?>" data-trigger-backup-code-download data-user="<?php echo esc_attr( $user->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
505 <?php esc_html_e( 'Download', 'wp-2fa' ); ?>
506 </button>
507 <button class="button button-secondary" type="submit" value="<?php esc_attr_e( 'Print', 'wp-2fa' ); ?>" data-trigger-print data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( $user->display_name ); ?>" data-website-url="<?php echo esc_attr( get_home_url() ); ?>">
508 <?php esc_html_e( 'Print', 'wp-2fa' ); ?>
509 </button>
510 </div>
511 </div>
512
513 </main>
514 </div>
515 </div>
516 </div>
517 </td>
518 </td>
519 </tr>
520 </tbody>
521 </table>
522 <?php
523
524 } else {
525 ?>
526 <h2>
527 <?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?>
528 </h2>
529 <?php
530 $class = 'notice notice-info wp-2fa-nag';
531 $grace_expiry = get_user_meta( $user->ID, 'wp_2fa_grace_period_expiry', true );
532 $reconfigure_2fa = get_user_meta( $user->ID, 'wp_2fa_user_needs_to_reconfigure_2fa', true );
533 if ( $reconfigure_2fa ) {
534 $message = esc_html__( 'The 2FA method you were using is no longer allowed on this website. Please reconfigure 2FA using one of the supported methods within', 'wp-2fa' );
535 } else {
536 $message = esc_html__( 'This website’s administrator requires you to enable 2FA authentication within', 'wp-2fa' );
537 }
538
539 ?>
540 <p class="description">
541 <?php echo $message; ?> <span class="grace-period-countdown" data-countdown-timestamp="<?php echo esc_attr( $grace_expiry ); ?>"></span
542 </p>
543 <p class="description">
544 <?php esc_html_e( 'Add two-factor authentication to strengthen the security of your WordPress user account.', 'wp-2fa' ); ?>
545 </p>
546 <table class="form-table" role="presentation">
547 <tbody>
548 <tr>
549 <th>
550 <label>
551 <?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?>
552 </label>
553 </th>
554
555 <td>
556 <a href="#" class="button button-primary remove-2fa" onclick="MicroModal.show('configure-2fa',{
557 onShow: modal => jQuery( '.wizard-step:first-of-type' ).addClass( 'active' ),
558 onClose: modal => jQuery( '.wizard-step.active' ).removeClass( 'active' ),
559 });"><?php esc_html_e( 'Configure 2FA', 'wp-2fa' ); ?></a>
560 </td>
561
562 <td>
563 <div class="wp2fa-modal micromodal-slide" id="configure-2fa" aria-hidden="true">
564 <div class="modal__overlay" tabindex="-1" data-micromodal-close>
565 <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
566 <header class="modal__header">
567 <button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
568 </header>
569 <main class="modal__content" id="modal-1-content">
570 <?php
571 $user = wp_get_current_user();
572 $enabled_method = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true );
573
574 // Grab key from user meta.
575 $key = Authentication::get_user_totp_key( $user->ID );
576
577 // If no key is present, lets make one.
578 if ( empty( $key ) ) {
579 $key = Authentication::generate_key();
580 $update = update_user_meta( $user->ID, 'wp_2fa_totp_key', $key );
581 }
582 $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' );
583 $validate_nonce = wp_create_nonce( 'wp-2fa-validate-authcode' );
584
585 // Setup site information, used when generating our QR code.
586 $site_name = get_bloginfo( 'name', 'display' );
587 $totp_title = apply_filters( 'wp_2fa_totp_title', $site_name . ':' . $user->user_login, $user );
588
589 if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) && ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) {
590 $intro_text = esc_html__( 'Choose the 2FA authentication method', 'wp-2fa' );
591 $sub_text = esc_html__( 'There are two methods available from which you can choose for 2FA:', 'wp-2fa' );
592 } else {
593 $intro_text = esc_html__( 'Choose the 2FA authentication method', 'wp-2fa' );
594 $sub_text = esc_html__( 'Only the below 2FA method is allowed on this website:', 'wp-2fa' );
595 }
596 ?>
597
598 <div class="wizard-step active">
599 <h3><?php echo sanitize_text_field( $intro_text ); ?></h3>
600 <p><?php echo sanitize_text_field( $sub_text ); ?></p>
601
602 <br>
603
604 <fieldset>
605 <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) ) { ?>
606 <div class="option-pill">
607 <label for="basic">
608 <input id="basic" name="wp_2fa_enabled_methods" type="radio" value="totp" checked>
609 <?php esc_html_e( 'One-time code generated with the Google authenticator app (most reliable and secure)', 'wp-2fa' ); ?>
610 </label>
611 <?php
612 printf( '<p class="description">%1$s <a href="https://www.wpwhitesecurity.com/google-authenticator-app-wordpress-2fa/" target="_blank">%2$s</a></p>', esc_html__( 'Note: this method requires you to install the Google Authenticator app on a smart device. The app is available on Google Play and the Apple Appstore. For more information on this method read our', 'wp-2fa' ), esc_html__( 'our guide for Google Authenticator.', 'wp-2fa' ) );
613 ?>
614 </div>
615 <?php } ?>
616 <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) { ?>
617 <br>
618 <div class="option-pill">
619 <label for="geek">
620 <input id="geek" name="wp_2fa_enabled_methods" type="radio" value="email">
621 <?php esc_html_e( 'One-time code sent to you over email', 'wp-2fa' ); ?>
622 </label>
623 </div>
624 <?php } ?>
625 </fieldset>
626 <br><br>
627 <a href="#" class="modal__btn modal__btn-primary button 2fa-choose-method" name="next_step_setting_modal_wizard" data-next-step><?php esc_html_e( 'Next Step', 'wp-2fa' ); ?></a>
628 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Close', 'wp-2fa' ); ?></button>
629 </div>
630
631 <div class="wizard-step" id="2fa-wizard-totp">
632 <fieldset>
633
634 <div class="step-setting-wrapper active">
635 <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3>
636 <div class="option-pill">
637 <ol>
638 <li><?php esc_html_e( 'Download the Google Authenticator app', 'wp-2fa' ); ?></li>
639 <li><?php esc_html_e( 'Click the plus sign (add new icon)', 'wp-2fa' ); ?></li>
640 <li><?php esc_html_e( 'Select \'Scan a barcode\'', 'wp-2fa' ); ?></li>
641 <li><?php esc_html_e( 'Scan the QR code to the right.', 'wp-2fa' ); ?></li>
642 </ol>
643 <p><?php esc_html_e( 'Otherwise, select Enter a provided key and type in the key below:', 'wp-2fa' ); ?></p>
644 <code><?php echo esc_html( $key ); ?></code>
645 </div>
646 <img style="right: 21px; position: absolute; top: 103px;" src="<?php echo esc_url( Authentication::get_google_qr_code( $totp_title, $key, $site_name ) ); ?>" id="wp-2fa-totp-qrcode" />
647 <br>
648 <div class="wp2fa-setup-actions">
649 <br>
650 <a class="button button-primary" name="next_step_setting"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></a>
651 </div>
652 </div>
653
654 <div class="step-setting-wrapper">
655 <h3><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h3>
656 <p><?php esc_html_e( 'Please type in the one-time code from your Google Authenticator app to finalize the setup.', 'wp-2fa' ); ?></p>
657 <br>
658 <fieldset>
659 <label for="2fa-totp-authcode">
660 <?php esc_html_e( 'Authentication Code:', 'wp-2fa' ); ?>
661 <input type="tel" name="wp-2fa-totp-authcode" id="wp-2fa-totp-authcode" class="input" value="" size="20" pattern="[0-9]*" />
662 </label>
663 <div class="verification-response"></div>
664 </fieldset>
665 <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" />
666 <br>
667 <a href="#" class="modal__btn modal__btn-primary button" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validate_nonce ); ?>"><?php esc_html_e( 'Validate & Save Configuration', 'wp-2fa' ); ?></a>
668 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
669 </div>
670
671 </fieldset>
672 </div>
673
674 <div class="wizard-step" id="2fa-wizard-email">
675 <fieldset>
676 <div class="step-setting-wrapper active">
677 <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3>
678 <p>
679 <?php esc_html_e( 'Please select the email address where the one-time code should be sent:', 'wp-2fa' ); ?>
680 </p>
681 <fieldset>
682 <label for="use_wp_email">
683 <input type="radio" name="wp_2fa_email_address" id="use_wp_email" value="<?php echo esc_attr( $user->user_email ); ?>" checked>
684 <span><?php esc_html_e( 'Use my WordPress user email (', 'wp-2fa' ); ?><small><?php echo esc_attr( $user->user_email ); ?></small><?php esc_html_e( ')', 'wp-2fa' ); ?></span>
685 </label>
686 <br/>
687 <label for="use_custom_email">
688 <input type="radio" name="wp_2fa_email_address" id="use_custom_email" value="use_custom_email">
689 <span><?php esc_html_e( 'Use a different email address:', 'wp-2fa' ); ?></span>
690 <input type="email" name="custom-email-address" id="custom-email-address" class="input wide" value=""/>
691 </label>
692 </fieldset>
693 <p class="description"><?php esc_html_e( 'Note: you should be able to access the mailbox of the email address to complete the following step.', 'wp-2fa' ); ?></p>
694 <div class="wp2fa-setup-actions">
695 <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>" data-trigger-setup-email data-user-id="<?php echo esc_attr( $user->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>" data-next-step="2fa-wizard-email"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></a>
696 </div>
697 </div>
698
699 <div class="step-setting-wrapper" id="2fa-wizard-email">
700 <h4><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h4>
701 <p><?php esc_html_e( 'Please type in the one-time code sent to your email address to finalize the setup.', 'wp-2fa' ); ?></p>
702 <fieldset>
703 <label for="2fa-email-authcode">
704 <?php esc_html_e( 'Authentication Code:', 'wp-2fa' ); ?>
705 <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*" />
706 </label>
707 <div class="verification-response"></div>
708 </fieldset>
709 <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" />
710
711 <a href="#" class="modal__btn modal__btn-primary button" data-validate-authcode-ajax data-nonce="<?php echo esc_attr( $validate_nonce ); ?>"><?php esc_html_e( 'Validate & Save Configuration', 'wp-2fa' ); ?></a>
712 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Cancel', 'wp-2fa' ); ?></button>
713 </div>
714 </fieldset>
715 </div>
716
717 <div class="wizard-step" id="2fa-wizard-setup-done">
718 <fieldset>
719
720 <h3><?php esc_html_e( 'Your website just got more secure!', 'wp-2fa' ); ?></h3>
721 <p><?php esc_html_e( 'Congratulations! You have enabled two-factor authentication for your user. You’ve just helped towards making this website more secure!', 'wp-2fa' ); ?></p>
722
723 <p><?php esc_html_e( 'You can exit this wizard now or continue to configure the plugin’s general settings. ', 'wp-2fa' ); ?></p>
724
725 <p class="description"><?php esc_html_e( 'Note: all the settings can be configured from the Settings > Two-factor Authentication entry of your WordPress menu.', 'wp-2fa' ); ?></p>
726
727 </fieldset>
728 <a href="#" class="modal__btn modal__btn-primary button" name="next_step_setting_modal_wizard" data-next-step><?php esc_html_e( 'Next Step', 'wp-2fa' ); ?></a>
729 <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window"><?php esc_html_e( 'Close', 'wp-2fa' ); ?></button>
730 </div>
731 </main>
732 </div>
733 </div>
734 </div>
735 </td>
736 </tr>
737 </tbody>
738 </table>
739 <?php
740
741 }
742
743 } elseif ( $is_user_excluded ) {
744
745 ?>
746 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
747 <p class="description"><?php esc_html_e( 'Add two-factor authentication to strengthen the security of your WordPress user account.', 'wp-2fa' ); ?></p>
748 <p class="description"><?php esc_html_e( 'Your user / role is not permitted to configure 2FA. Contact your administrator for more information.', 'wp-2fa' ); ?></p>
749 <?php
750
751 } elseif ( $grace_period_expired && current_user_can( 'manage_options' ) ) {
752 ?>
753 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
754 <table class="form-table" role="presentation">
755 <tbody>
756 <tr>
757 <th><label><?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?></label></th>
758 <td>
759 <?php
760 $url = add_query_arg(
761 array(
762 'action' => 'unlock_account',
763 'user_id' => $user->ID,
764 'wp_2fa_nonce' => wp_create_nonce( 'wp-2fa-unlock-account-nonce' ),
765 ),
766 admin_url( 'user-edit.php' )
767 );
768
769 if ( $grace_period_expired ) {
770 ?>
771 <a href="<?php echo esc_url( $url ); ?>" class="button button-primary"><?php esc_html_e( 'Unlock user and reset the grace period', 'wp-2fa' ); ?></a>
772 <?php
773 }
774 ?>
775 </td>
776 </tr>
777 </tbody>
778 </table>
779 <?php
780 } elseif ( ! $grace_period_expired && current_user_can( 'manage_options' ) && ! empty( $enabled_methods ) ) {
781 ?>
782 <h2><?php esc_html_e( 'WP 2FA Settings', 'wp-2fa' ); ?></h2>
783 <p class="description"><?php esc_html_e( 'By resetting this user\'s 2FA configuration you disable the currently configured 2FA so the user can log back in using a usemame and a password only. *the user if enforced to setup 2FA the user will get a prompt upon logging in, from where 2FA can be configured. The user has to configure 2FA within the configured grace period.', 'wp-2fa' ); ?></p>
784 <table class="form-table" role="presentation">
785 <tbody>
786 <tr>
787 <th><label><?php esc_html_e( '2-Factor authentication', 'wp-2fa' ); ?></label></th>
788 <td>
789 <?php
790 // Create remove 2fa link.
791 $url = add_query_arg(
792 array(
793 'action' => 'remove_user_2fa',
794 'user_id' => $user->ID,
795 'wp_2fa_nonce' => wp_create_nonce( 'wp-2fa-remove-user-2fa-nonce' ),
796 'admin_reset' => 'yes',
797 ),
798 admin_url( 'user-edit.php' )
799 );
800 ?>
801 <a href="<?php echo esc_url( $url ); ?>" class="button button-primary"><?php esc_html_e( 'Reset 2FA configuration', 'wp-2fa' ); ?></a>
802 </td>
803 </tr>
804 </tbody>
805 </table>
806 <?php
807 }
808 }
809
810 /**
811 * Add custom unlock account link to user edit admin list.
812 *
813 * @param string $actions Default actions.
814 * @param object $user_object User data.
815 * @return string Appended actions.
816 */
817 public function user_2fa_row_actions( $actions, $user_object ) {
818 $nonce = wp_create_nonce( 'wp-2fa-unlock-account-nonce' );
819 $grace_period_expired = get_user_meta( $user_object->ID, 'wp_2fa_user_grace_period_expired', true );
820 $url = add_query_arg(
821 array(
822 'action' => 'unlock_account',
823 'user_id' => $user_object->ID,
824 'wp_2fa_nonce' => $nonce,
825 ),
826 admin_url( 'users.php' )
827 );
828
829 if ( $grace_period_expired ) {
830 $actions['edit_badges'] = '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Unlock user', 'wp-2fa' ) . '</a>';
831 }
832 return $actions;
833 }
834
835 /**
836 * Save user profile information.
837 */
838 public function save_user_2fa_options() {
839 // Grab current user.
840 $user = wp_get_current_user();
841
842 // Setup some empty arrays which will may fill later, should an error arise along the way.
843 $notices = array();
844 $errors = array();
845
846 // Grab key from the $_POST.
847 if ( isset( $_POST['wp-2fa-totp-key'] ) ) {
848 $current_key = sanitize_text_field( wp_unslash( $_POST['wp-2fa-totp-key'] ) );
849 }
850
851 // Grab authcode and ensure its a number.
852 if ( isset( $_POST['wp-2fa-totp-authcode'] ) ) {
853 $_POST['wp-2fa-totp-authcode'] = (int) $_POST['wp-2fa-totp-authcode'];
854 }
855
856 if ( ! isset( $_POST['custom-email-address'] ) ) {
857 update_user_meta( $user->ID, 'wp_2fa_nominated_email_address', $_POST['email'] );
858 } elseif ( isset( $_POST['custom-email-address'] ) ) {
859 update_user_meta( $user->ID, 'wp_2fa_nominated_email_address', sanitize_email( wp_unslash( $_POST['custom-email-address'] ) ) );
860 }
861
862 // Now lets grab the users enabled 2fa methods.
863 $get_array = filter_input_array( INPUT_GET );
864 $selected_method = sanitize_text_field( $get_array['enabled_methods'] );
865 // Check its one of our options.
866 if ( isset( $_POST['wp_2fa_enabled_methods'] ) && 'totp' === $_POST['wp_2fa_enabled_methods'] || isset( $_POST['wp_2fa_enabled_methods'] ) && 'email' === $_POST['wp_2fa_enabled_methods'] ) {
867 update_user_meta( $user->ID, 'wp_2fa_enabled_methods', sanitize_text_field( wp_unslash( $_POST['wp_2fa_enabled_methods'] ) ) );
868 delete_user_meta( $user->ID, 'wp_2fa_grace_period_expiry' );
869 }
870
871 if ( isset( $_POST['wp-2fa-email-authcode'] ) && ! empty( $_POST['wp-2fa-email-authcode'] ) ) {
872 update_user_meta( $user->ID, 'wp_2fa_enabled_methods', 'email' );
873 delete_user_meta( $user->ID, 'wp_2fa_grace_period_expiry' );
874 }
875
876 if ( isset( $_POST['wp-2fa-totp-authcode'] ) && ! empty( $_POST['wp-2fa-totp-authcode'] ) ) {
877 update_user_meta( $user->ID, 'wp_2fa_enabled_methods', 'totp' );
878 delete_user_meta( $user->ID, 'wp_2fa_grace_period_expiry' );
879 }
880 }
881
882 /**
883 * Validate a user's code when setting up 2fa via the inline form.
884 *
885 * @return json result of validation.
886 */
887 public function validate_authcode_via_ajax() {
888 check_ajax_referer( 'wp-2fa-validate-authcode' );
889
890 if ( isset( $_POST['form'] ) ) {
891 $input = $_POST['form'];
892 } else {
893 return 'No form';
894 }
895
896 $user = wp_get_current_user();
897
898 // Setup some empty arrays which will may fill later, should an error arise along the way.
899 $notices = array();
900 $our_errors = '';
901
902 // Grab key from the $_POST.
903 if ( isset( $input['wp-2fa-totp-key'] ) ) {
904 $current_key = sanitize_text_field( wp_unslash( $input['wp-2fa-totp-key'] ) );
905 }
906
907 // Grab authcode and ensure its a number.
908 if ( isset( $input['wp-2fa-totp-authcode'] ) ) {
909 $input['wp-2fa-totp-authcode'] = (int) $input['wp-2fa-totp-authcode'];
910 }
911
912 // Check if we are dealing with totp or email, if totp validate and store a new secret key.
913 if ( ! empty( $input['wp-2fa-totp-authcode'] ) && ! empty( $current_key ) ) {
914 if ( Authentication::is_valid_key( $current_key ) || ! is_numeric( $input['wp-2fa-totp-authcode'] ) ) {
915 if ( ! Authentication::is_valid_authcode( $current_key, sanitize_text_field( wp_unslash( $input['wp-2fa-totp-authcode'] ) ) ) ) {
916 $our_errors = esc_html__( 'Invalid Two Factor Authentication code.', 'wp-2fa' );
917 }
918 } else {
919 $our_errors = esc_html__( 'Invalid Two Factor Authentication secret key.', 'wp-2fa' );
920 }
921
922 // If its not totp, is it email.
923 } elseif ( ! empty( $input['wp-2fa-email-authcode'] ) ) {
924 if ( ! Authentication::validate_token( $user->ID, sanitize_text_field( wp_unslash( $input['wp-2fa-email-authcode'] ) ) ) ) {
925 $our_errors = __( 'Invalid Email Authentication code.', 'wp-2fa' );
926 }
927 } else {
928 $our_errors = __( 'Please enter the code to finalize the 2FA setup.', 'wp-2fa' );
929 }
930
931 if ( ! empty( $our_errors ) ) {
932 // Send the response.
933 wp_send_json_error(
934 array(
935 'error' => $our_errors,
936 )
937 );
938 } else {
939 // Send the response.
940 wp_send_json_success();
941 }
942 }
943 }
944