SettingsPage.php
5 years ago
SetupWizard.php
5 years ago
UserNotices.php
5 years ago
UserProfile.php
5 years ago
UserRegistered.php
5 years ago
SetupWizard.php
1460 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\Utils\GenerateModal as GenerateModal; |
| 9 | use \WP2FA\BackgroundProcessing\Enforce2FA as Enforce2FA; |
| 10 | use \WP2FA\Admin\SettingsPage as SettingsPage; |
| 11 | use \WP2FA\Utils\UserUtils as UserUtils; |
| 12 | use \WP2FA\Admin\UserProfile as UserProfile; |
| 13 | |
| 14 | /** |
| 15 | * Our class for creating a step by step wizard for easy configuration. |
| 16 | */ |
| 17 | class SetupWizard { |
| 18 | |
| 19 | /** |
| 20 | * Wizard Steps |
| 21 | * |
| 22 | * @var array |
| 23 | */ |
| 24 | private $wizard_steps; |
| 25 | |
| 26 | /** |
| 27 | * Current Step |
| 28 | * |
| 29 | * @var string |
| 30 | */ |
| 31 | private $current_step; |
| 32 | |
| 33 | /** |
| 34 | * Notices Meta key |
| 35 | * |
| 36 | * @var array |
| 37 | */ |
| 38 | const NOTICES_META_KEY = 'wp_2fa_totp_notices'; |
| 39 | |
| 40 | /** |
| 41 | * Method: Constructor. |
| 42 | */ |
| 43 | public function __construct() { } |
| 44 | |
| 45 | /** |
| 46 | * Add setup admin page. This is empty on purpose. |
| 47 | */ |
| 48 | public function admin_menus() { |
| 49 | add_dashboard_page( '', '', 'read', 'wp-2fa-setup', '' ); |
| 50 | } |
| 51 | |
| 52 | public function network_admin_menus() { |
| 53 | add_dashboard_page( 'index.php', '', 'read', 'wp-2fa-setup', '' ); |
| 54 | } |
| 55 | |
| 56 | /** |
| 57 | * Setup Page Start. |
| 58 | */ |
| 59 | public function setup_page() { |
| 60 | // Get page argument from $_GET array. |
| 61 | $page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING ); |
| 62 | if ( empty( $page ) || 'wp-2fa-setup' !== $page ) { |
| 63 | return; |
| 64 | } |
| 65 | |
| 66 | // Clear out any old notices. |
| 67 | $user = wp_get_current_user(); |
| 68 | delete_user_meta( $user->ID, self::NOTICES_META_KEY ); |
| 69 | |
| 70 | // First lets check if any options have been saved. |
| 71 | $settings_saved = true; |
| 72 | $settings = WP2FA::get_wp2fa_setting(); |
| 73 | if ( empty( $settings ) || ! isset( $settings ) ) { |
| 74 | $settings_saved = false; |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Wizard Steps. |
| 79 | */ |
| 80 | $get_array = filter_input_array( INPUT_GET ); |
| 81 | if ( isset( $get_array['wizard_type'] ) ) { |
| 82 | $wizard_type = sanitize_text_field( $get_array['wizard_type'] ); |
| 83 | } else { |
| 84 | $wizard_type = 'default'; |
| 85 | } |
| 86 | |
| 87 | $is_user_forced_to_setup = get_user_meta( $user->ID, 'wp_2fa_user_enforced_instantly', true ); |
| 88 | if ( ! empty( $is_user_forced_to_setup ) ) { |
| 89 | add_filter( 'wp_2fa_wizard_default_steps', array( $this, 'wp_2fa_add_intro_step' ) ); |
| 90 | } |
| 91 | |
| 92 | $user_type = UserUtils::determine_user_2fa_status( $user ); |
| 93 | |
| 94 | $wizard_steps = array( |
| 95 | 'welcome' => array( |
| 96 | 'name' => esc_html__( 'Welcome', 'wp-2fa' ), |
| 97 | 'content' => array( $this, 'wp_2fa_step_welcome' ), |
| 98 | 'wizard_type' => 'welcome_wizard', |
| 99 | ), |
| 100 | 'user_choose_2fa_method' => array( |
| 101 | 'name' => esc_html__( 'Choose Method', 'wp-2fa' ), |
| 102 | 'content' => array( $this, 'wp_2fa_step_user_choose_method' ), |
| 103 | 'save' => array( $this, 'wp_2fa_step_user_choose_method_save' ), |
| 104 | 'wizard_type' => 'welcome_wizard', |
| 105 | ), |
| 106 | 'choose_2fa_method' => array( |
| 107 | 'name' => esc_html__( 'Choose Method', 'wp-2fa' ), |
| 108 | 'content' => array( $this, 'wp_2fa_step_choose_method' ), |
| 109 | 'save' => array( $this, 'wp_2fa_step_choose_method_save' ), |
| 110 | 'wizard_type' => 'welcome_wizard', |
| 111 | ), |
| 112 | 'setup_method' => array( |
| 113 | 'name' => esc_html__( 'Setup the 2FA method', 'wp-2fa' ), |
| 114 | 'content' => array( $this, 'wp_2fa_step_setup_authenticator' ), |
| 115 | 'save' => array( $this, 'wp_2fa_step_setup_authenticator_save' ), |
| 116 | 'wizard_type' => 'welcome_wizard', |
| 117 | ), |
| 118 | 'finish' => array( |
| 119 | 'name' => esc_html__( 'Setup Finish', 'wp-2fa' ), |
| 120 | 'content' => array( $this, 'wp_2fa_step_finish' ), |
| 121 | 'save' => array( $this, 'wp_2fa_step_finish_save' ), |
| 122 | 'wizard_type' => 'welcome_wizard', |
| 123 | ), |
| 124 | 'settings_configuation' => array( |
| 125 | 'name' => esc_html__( 'Select 2FA Methods', 'wp-2fa' ), |
| 126 | 'content' => array( $this, 'wp_2fa_step_global_2fa_methods' ), |
| 127 | 'save' => array( $this, 'wp_2fa_step_global_2fa_methods_save' ), |
| 128 | 'wizard_type' => 'welcome_wizard', |
| 129 | ), |
| 130 | 'backup_codes' => array( |
| 131 | 'name' => esc_html__( 'Backup Codes', 'wp-2fa' ), |
| 132 | 'content' => array( $this, 'wp_2fa_step_backup_codes' ), |
| 133 | 'save' => array( $this, 'wp_2fa_step_backup_codes_save' ), |
| 134 | 'wizard_type' => array( 'welcome_wizard', 'backup_codes_wizard' ), |
| 135 | ), |
| 136 | 'reconfigure_method' => array( |
| 137 | 'name' => esc_html__( 'Setup the Authenticator 2FA', 'wp-2fa' ), |
| 138 | 'content' => array( $this, 'wp_2fa_step_reconfigure_authenticator' ), |
| 139 | 'save' => array( $this, 'wp_2fa_step_reconfigure_authenticator_save' ), |
| 140 | 'wizard_type' => 'reconfigure_wizard', |
| 141 | ), |
| 142 | ); |
| 143 | |
| 144 | // Admin user setting up fresh install of 2FA plugin. |
| 145 | if ( in_array( 'can_manage_options', $user_type, true ) && ! $settings_saved ) { |
| 146 | unset( $wizard_steps['user_choose_2fa_method'] ); |
| 147 | unset( $wizard_steps['reconfigure_method'] ); |
| 148 | } |
| 149 | |
| 150 | // Ensure user has minimum capabitlies needed to be here. |
| 151 | if ( in_array( 'can_read', $user_type, true ) && $settings_saved ) { |
| 152 | |
| 153 | switch ( $wizard_type ) { |
| 154 | case 'user_2fa_config': |
| 155 | $wizard_steps = array_intersect_key( $wizard_steps, array_flip( ['user_choose_2fa_method', 'setup_method', 'finish', 'backup_codes'] ) ); |
| 156 | break; |
| 157 | |
| 158 | case 'backup_codes_config': |
| 159 | $wizard_steps = array_intersect_key( $wizard_steps, array_flip( ['backup_codes'] ) ); |
| 160 | break; |
| 161 | |
| 162 | case 'user_reconfigure_config': |
| 163 | $wizard_steps = array_intersect_key( $wizard_steps, array_flip( ['reconfigure_method'] ) ); |
| 164 | break; |
| 165 | |
| 166 | default: |
| 167 | $wizard_steps = array_intersect_key( $wizard_steps, array_flip( ['choose_2fa_method', 'setup_method', 'finish', 'backup_codes', 'reconfigure_method' ] ) ); |
| 168 | } |
| 169 | |
| 170 | // Remove 1st step if only one method is available. |
| 171 | if ( empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) || empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) { |
| 172 | unset( $wizard_steps['choose_2fa_method'] ); |
| 173 | } |
| 174 | |
| 175 | // If the user has codes setup already, no need to add the slide. |
| 176 | if ( ! in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) && 'backup_codes_config' !== $wizard_type ) { |
| 177 | unset( $wizard_steps['backup_codes'] ); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | /** |
| 182 | * Filter: `Wizard Default Steps` |
| 183 | * |
| 184 | * WSAL filter to filter wizard steps before they are displayed. |
| 185 | * |
| 186 | * @param array $wizard_steps – Wizard Steps. |
| 187 | */ |
| 188 | $this->wizard_steps = apply_filters( 'wp_2fa_wizard_default_steps', $wizard_steps ); |
| 189 | |
| 190 | // Set current step. |
| 191 | $current_step = filter_input( INPUT_GET, 'current-step', FILTER_SANITIZE_STRING ); |
| 192 | $this->current_step = ! empty( $current_step ) ? $current_step : current( array_keys( $this->wizard_steps ) ); |
| 193 | |
| 194 | /** |
| 195 | * Enqueue Scripts. |
| 196 | */ |
| 197 | wp_enqueue_style( |
| 198 | 'wp_2fa_setup_wizard', |
| 199 | Core\style_url( 'setup-wizard', 'admin' ), |
| 200 | array(), |
| 201 | WP_2FA_VERSION |
| 202 | ); |
| 203 | |
| 204 | wp_enqueue_script( |
| 205 | 'wp_2fa_admin', |
| 206 | Core\script_url( 'admin', 'admin' ), |
| 207 | array( 'jquery-ui-widget', 'jquery-ui-core', 'jquery-ui-autocomplete' ), |
| 208 | WP_2FA_VERSION, |
| 209 | true |
| 210 | ); |
| 211 | |
| 212 | wp_enqueue_script( |
| 213 | 'wp_2fa_micromodal', |
| 214 | Core\script_url( 'micro-modal', 'admin' ), |
| 215 | WP_2FA_VERSION, |
| 216 | true |
| 217 | ); |
| 218 | |
| 219 | // Data array. |
| 220 | $data_array = array( |
| 221 | 'ajaxURL' => admin_url( 'admin-ajax.php' ), |
| 222 | 'roles' => WP2FA::wp_2fa_get_roles(), |
| 223 | 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ) |
| 224 | ); |
| 225 | wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array ); |
| 226 | |
| 227 | // Data array. |
| 228 | $data_array = array( |
| 229 | 'ajaxURL' => admin_url( 'admin-ajax.php' ), |
| 230 | 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ), |
| 231 | 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ), |
| 232 | 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ), |
| 233 | 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ), |
| 234 | ); |
| 235 | wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array ); |
| 236 | |
| 237 | /** |
| 238 | * Save Wizard Settings. |
| 239 | */ |
| 240 | $save_step = filter_input( INPUT_POST, 'save_step', FILTER_SANITIZE_STRING ); |
| 241 | if ( ! empty( $save_step ) && ! empty( $this->wizard_steps[ $this->current_step ]['save'] ) ) { |
| 242 | call_user_func( $this->wizard_steps[ $this->current_step ]['save'] ); |
| 243 | } |
| 244 | |
| 245 | $this->setup_page_header(); |
| 246 | $this->setup_page_steps(); |
| 247 | $this->setup_page_content(); |
| 248 | $this->setup_page_footer(); |
| 249 | |
| 250 | exit; |
| 251 | } |
| 252 | |
| 253 | /** |
| 254 | * Setup Page Header. |
| 255 | */ |
| 256 | private function setup_page_header() { |
| 257 | ?> |
| 258 | <!DOCTYPE html> |
| 259 | <html <?php language_attributes(); ?>> |
| 260 | <head> |
| 261 | <meta name="viewport" content="width=device-width" /> |
| 262 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| 263 | <title><?php esc_html_e( 'WP 2FA › Setup Wizard', 'wp-2fa' ); ?></title> |
| 264 | <?php wp_print_scripts( 'jquery' ); ?> |
| 265 | <?php wp_print_scripts( 'jquery-ui-core' ); ?> |
| 266 | <?php wp_print_scripts( 'wp_2fa_setup_wizard' ); ?> |
| 267 | <?php wp_print_scripts( 'wp_2fa_micromodal' ); ?> |
| 268 | <?php wp_print_scripts( 'wp_2fa_admin' ); ?> |
| 269 | <?php wp_print_styles( 'common' ); ?> |
| 270 | <?php wp_print_styles( 'forms' ); ?> |
| 271 | <?php wp_print_styles( 'buttons' ); ?> |
| 272 | <?php wp_print_styles( 'wp-jquery-ui-dialog' ); ?> |
| 273 | <?php wp_print_styles( 'wp_2fa_admin' ); ?> |
| 274 | <?php do_action( 'admin_print_styles' ); ?> |
| 275 | </head> |
| 276 | <body class="wp2fa-setup wp-core-ui"> |
| 277 | <div class="setup-wizard-wrapper"> |
| 278 | <h1 id="wp2fa-logo"><a href="https://wpsecurityauditlog.com" target="_blank"><img src="<?php echo esc_url( WP_2FA_URL . '/dist/images/wizard-logo.png' ); ?>"></a></h1> |
| 279 | <?php |
| 280 | } |
| 281 | |
| 282 | /** |
| 283 | * Setup Page Footer. |
| 284 | */ |
| 285 | private function setup_page_footer() { |
| 286 | $user = wp_get_current_user(); |
| 287 | $roles = (array) $user->roles; |
| 288 | |
| 289 | $redirect = get_edit_profile_url( $user->ID ); |
| 290 | ?> |
| 291 | <div class="wp2fa-setup-footer"> |
| 292 | <?php if ( 'welcome' !== $this->current_step && 'finish' !== $this->current_step ) : // Don't show the link on the first & last step. ?> |
| 293 | <?php if ( ! get_user_meta( $user->ID, 'wp_2fa_user_enforced_instantly', true ) ) : ?> |
| 294 | <a class="close-wizard-link" href="<?php echo esc_url( $redirect ); ?>"><?php esc_html_e( 'Close Wizard', 'wp-2fa' ); ?></a> |
| 295 | <?php endif; ?> |
| 296 | <?php endif; ?> |
| 297 | </div> |
| 298 | </div> |
| 299 | |
| 300 | <?php |
| 301 | echo GenerateModal::generate_modal( |
| 302 | 'confirm-change-2fa', |
| 303 | __( 'Change 2FA Method?', 'wp-2fa' ), |
| 304 | __( 'By switching to a new method the previously used method will be disabled.', 'wp-2fa' ), |
| 305 | [ |
| 306 | '<a href="#" class="modal__btn modal__btn-primary button-primary" data-trigger-submit-form>'. __( 'OK', 'wp-2fa' ) .'</a>', |
| 307 | '<button class="modal__btn button-secondary" data-micromodal-close aria-label="Close this dialog window">'. __( 'No thanks', 'wp-2fa' ) .'</button>' |
| 308 | ] |
| 309 | ); |
| 310 | ?> |
| 311 | </body> |
| 312 | </html> |
| 313 | <?php |
| 314 | } |
| 315 | |
| 316 | /** |
| 317 | * Setup Page Steps. |
| 318 | */ |
| 319 | private function setup_page_steps() { |
| 320 | ?> |
| 321 | <ul class="steps"> |
| 322 | <?php |
| 323 | foreach ( $this->wizard_steps as $key => $step ) : |
| 324 | if ( 'welcome_wizard' === $step['wizard_type'] || is_array( $step['wizard_type'] ) && in_array( 'welcome_wizard', $step['wizard_type'], true ) ) : |
| 325 | if ( $key === $this->current_step ) : |
| 326 | ?> |
| 327 | <li class="is-active"><?php echo esc_html( $step['name'] ); ?></li> |
| 328 | <?php |
| 329 | else : |
| 330 | ?> |
| 331 | <li><?php echo esc_html( $step['name'] ); ?></li> |
| 332 | <?php |
| 333 | endif; |
| 334 | endif; |
| 335 | endforeach; |
| 336 | ?> |
| 337 | </ul> |
| 338 | <?php |
| 339 | } |
| 340 | |
| 341 | /** |
| 342 | * Get Next Step URL. |
| 343 | * |
| 344 | * @return string |
| 345 | */ |
| 346 | private function get_next_step() { |
| 347 | // Get current step. |
| 348 | $current_step = $this->current_step; |
| 349 | |
| 350 | // Array of step keys. |
| 351 | $keys = array_keys( $this->wizard_steps ); |
| 352 | if ( end( $keys ) === $current_step ) { // If last step is active then return WP Admin URL. |
| 353 | return admin_url(); |
| 354 | } |
| 355 | |
| 356 | // Search for step index in step keys. |
| 357 | $step_index = array_search( $current_step, $keys, true ); |
| 358 | if ( false === $step_index ) { // If index is not found then return empty string. |
| 359 | return ''; |
| 360 | } |
| 361 | |
| 362 | // Return next step. |
| 363 | return add_query_arg( 'current-step', $keys[ $step_index + 1 ] ); |
| 364 | } |
| 365 | |
| 366 | /** |
| 367 | * Setup Page Content. |
| 368 | */ |
| 369 | private function setup_page_content() { |
| 370 | ?> |
| 371 | <div class="wp2fa-setup-content"> |
| 372 | <?php |
| 373 | if ( ! empty( $this->wizard_steps[ $this->current_step ]['content'] ) ) { |
| 374 | call_user_func( $this->wizard_steps[ $this->current_step ]['content'] ); |
| 375 | } |
| 376 | ?> |
| 377 | </div> |
| 378 | <?php |
| 379 | } |
| 380 | |
| 381 | /** |
| 382 | * Step View: `Welcome` |
| 383 | */ |
| 384 | private function wp_2fa_step_welcome() { |
| 385 | // Grab current user. |
| 386 | $user = wp_get_current_user(); |
| 387 | |
| 388 | if ( WP2FA::is_this_multisite() ) { |
| 389 | $redirect = add_query_arg( 'page', 'wp-2fa-settings', network_admin_url( 'settings.php' ) ); |
| 390 | } else { |
| 391 | // Otherwise redirect to main audit log view. |
| 392 | $redirect = add_query_arg( 'page', 'wp-2fa-settings', admin_url( 'options-general.php' ) ); |
| 393 | } |
| 394 | |
| 395 | ?> |
| 396 | <h3><?php esc_html_e( 'Let us help you get started', 'wp-2fa' ); ?></h3> |
| 397 | <p><?php esc_html_e( 'Thank you for installing WP 2FA. This wizard will assist you setup two-factor authentication (2FA) for your WordPress user and configure the plugin’s generic settings.', 'wp-2fa' ); ?></p> |
| 398 | |
| 399 | <div class="wp2fa-setup-actions"> |
| 400 | <a class="button button-primary" |
| 401 | href="<?php echo esc_url( $this->get_next_step() ); ?>"> |
| 402 | <?php esc_html_e( 'Let’s get started!', 'wp-2fa' ); ?> |
| 403 | </a> |
| 404 | <a class="button button-secondary" |
| 405 | href="<?php echo esc_url( $redirect ); ?>"> |
| 406 | <?php esc_html_e( 'Skip Wizard - I know how to do this', 'wp-2fa' ); ?> |
| 407 | </a> |
| 408 | </div> |
| 409 | <?php |
| 410 | } |
| 411 | |
| 412 | /** |
| 413 | * Step View: `Choose Methods` |
| 414 | */ |
| 415 | private function wp_2fa_step_choose_method() { |
| 416 | ?> |
| 417 | <form method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 418 | <?php wp_nonce_field( 'wp2fa-step-choose-method' ); ?> |
| 419 | |
| 420 | <?php |
| 421 | if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) && ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) { |
| 422 | $intro_text = esc_html__( 'Let’s get started; Choose the two-factor authentication method', 'wp-2fa' ); |
| 423 | $sub_text = esc_html__( 'There are two methods available from which you can choose for 2FA:', 'wp-2fa' ); |
| 424 | } else { |
| 425 | $intro_text = esc_html__( 'Let’s get started', 'wp-2fa' ); |
| 426 | $sub_text = esc_html__( 'Only the below 2FA method is allowed on this website:', 'wp-2fa' ); |
| 427 | } |
| 428 | ?> |
| 429 | |
| 430 | <fieldset> |
| 431 | <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) ) { ?> |
| 432 | <div class="option-pill"> |
| 433 | <label for="basic"> |
| 434 | <input id="basic" name="wp_2fa_enabled_methods" type="radio" value="totp" checked> |
| 435 | <?php esc_html_e( 'One-time code generated with your app of choice (most reliable and secure)', 'wp-2fa' ); ?> |
| 436 | </label> |
| 437 | <?php |
| 438 | printf( '<p class="description">%1$s <a href="https://www.wpwhitesecurity.com/support/kb/configuring-2fa-apps/" target="_blank">%2$s</a> %3$s</p>', esc_html__( 'Note: This method requires you to install one of the following 2FA apps: Google Authenticator, FreeOTP, Microsoft Authenticator, Duo Security, Authy, LastPass and Okta Verify. All of these apps are free and can be downloaded from the Google Play and Apple Appstore. Read our guides on', 'wp-2fa' ), esc_html__( 'our knowledge base', 'wp-2fa' ), esc_html__( 'for more information on how to setup these apps.', 'wp-2fa' ) ); |
| 439 | ?> |
| 440 | </div> |
| 441 | <?php } ?> |
| 442 | <?php if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) { ?> |
| 443 | <div class="option-pill"> |
| 444 | <label for="geek"> |
| 445 | <input id="geek" name="wp_2fa_enabled_methods" type="radio" value="email"> |
| 446 | <?php esc_html_e( 'One-time code sent to you over email', 'wp-2fa' ); ?> |
| 447 | </label> |
| 448 | </div> |
| 449 | <?php } ?> |
| 450 | </fieldset> |
| 451 | <div class="wp2fa-setup-actions"> |
| 452 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'Next', 'wp-2fa' ); ?>"><?php esc_html_e( 'Next', 'wp-2fa' ); ?></button> |
| 453 | </div> |
| 454 | </form> |
| 455 | <?php |
| 456 | } |
| 457 | |
| 458 | /** |
| 459 | * Step Save: `Choose Method` |
| 460 | */ |
| 461 | private function wp_2fa_step_choose_method_save() { |
| 462 | // Check nonce. |
| 463 | check_admin_referer( 'wp2fa-step-choose-method' ); |
| 464 | |
| 465 | // Grab current user. |
| 466 | $user = wp_get_current_user(); |
| 467 | |
| 468 | // Add our enabled methods to the user metadata. |
| 469 | if ( isset( $_POST['wp_2fa_enabled_methods'] ) ) { |
| 470 | $next = add_query_arg( 'enabled_methods', sanitize_text_field( wp_unslash( $_POST['wp_2fa_enabled_methods'] ) ), $this->get_next_step() ); |
| 471 | wp_safe_redirect( esc_url_raw( $next ) ); |
| 472 | } |
| 473 | |
| 474 | exit(); |
| 475 | } |
| 476 | |
| 477 | /** |
| 478 | * Choose user 2FA method |
| 479 | */ |
| 480 | private function wp_2fa_step_user_choose_method() { |
| 481 | $user = wp_get_current_user(); |
| 482 | $enabled_method = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true ); |
| 483 | |
| 484 | ?> |
| 485 | <form id="wp2fa-setup-form" method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 486 | <?php wp_nonce_field( 'wp2fa-step-choose-method' ); ?> |
| 487 | |
| 488 | <?php |
| 489 | $nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . $user->ID ); |
| 490 | // Change text if this is the user configuring there 2fa settings |
| 491 | // Filter $_GET array for security. |
| 492 | $get_array = filter_input_array( INPUT_GET ); |
| 493 | // If this is the user setting things up, lets show nice message. |
| 494 | if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) && ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) { |
| 495 | $intro_text = esc_html__( 'Choose the 2FA authentication method', 'wp-2fa' ); |
| 496 | $sub_text = esc_html__( 'There are two methods available from which you can choose for 2FA:', 'wp-2fa' ); |
| 497 | } else { |
| 498 | $intro_text = esc_html__( 'Choose the 2FA authentication method', 'wp-2fa' ); |
| 499 | $sub_text = esc_html__( 'Only the below 2FA method is allowed on this website:', 'wp-2fa' ); |
| 500 | } |
| 501 | ?> |
| 502 | <h3><?php echo sanitize_text_field( $intro_text ); ?></h3> |
| 503 | <p><?php echo sanitize_text_field( $sub_text ); ?></p> |
| 504 | |
| 505 | <fieldset> |
| 506 | <?php |
| 507 | if ( 'totp' === $enabled_method ) { |
| 508 | ?> |
| 509 | <div class="option-pill"> |
| 510 | <label for="basic"> |
| 511 | <input id="basic" name="wp_2fa_enabled_methods" type="radio" value="totp" checked> |
| 512 | <?php esc_html_e( 'Reconfigure the 2FA App', 'wp-2fa' ); ?> |
| 513 | </label> |
| 514 | <p class="description"><?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' ); ?> |
| 515 | </p> |
| 516 | <button class="button button-primary" data-trigger-reset-key data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( $user->ID ); ?>" type="submit" name="save_step" value="<?php esc_attr_e( 'Reset', 'wp-2fa' ); ?>"><?php esc_html_e( 'Reset', 'wp-2fa' ); ?></button> |
| 517 | </div> |
| 518 | <div class="option-pill"> |
| 519 | <p class="description"> |
| 520 | <label for="geek"> |
| 521 | <input id="email" name="wp_2fa_enabled_methods" type="radio" value="email"> |
| 522 | <?php esc_html_e( 'One-time code sent to you over email', 'wp-2fa' ); ?> |
| 523 | </label> |
| 524 | </p> |
| 525 | <a href="#" class="button button-primary change-2fa-confirm" onclick="MicroModal.show('confirm-change-2fa');" data-check-on-click="#email"><?php esc_html_e( 'Configure and use this method instead', 'wp-2fa' ); ?></a> |
| 526 | <button class="button button-primary change-2fa-confirm hidden" type="submit" name="save_step" value="<?php esc_attr_e( 'Configure and use this method instead', 'wp-2fa' ); ?>"><?php esc_html_e( 'Submit', 'wp-2fa' ); ?></button> |
| 527 | </div> |
| 528 | <?php |
| 529 | } |
| 530 | if ( 'email' === $enabled_method ) { |
| 531 | ?> |
| 532 | <div class="option-pill"> |
| 533 | <p class="description"> |
| 534 | <label for="geek"> |
| 535 | <input id="geek" name="wp_2fa_enabled_methods" type="radio" value="email" checked> |
| 536 | <?php esc_html_e( 'Reconfigure the email address for email 2FA', 'wp-2fa' ); ?> |
| 537 | </label> |
| 538 | </p> |
| 539 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'Reconfigure email 2FA', 'wp-2fa' ); ?>"><?php esc_html_e( 'Reconfigure email 2FA', 'wp-2fa' ); ?></button> |
| 540 | </div> |
| 541 | <div class="option-pill"> |
| 542 | <p class="description"> |
| 543 | <label for="wp_2fa_enabled_methods"> |
| 544 | <input id="totp" name="wp_2fa_enabled_methods" type="radio" value="totp"> |
| 545 | <?php esc_html_e( 'One-time code generated with your app of choice (most reliable and secure)', 'wp-2fa' ); ?> |
| 546 | </label> |
| 547 | </p> |
| 548 | <a href="#" class="button button-primary change-2fa-confirm" onclick="MicroModal.show('confirm-change-2fa');" data-check-on-click="#totp"><?php esc_html_e( 'Configure and use this method instead', 'wp-2fa' ); ?></a> |
| 549 | <button class="button button-primary change-2fa-confirm hidden" type="submit" name="save_step" value="<?php esc_attr_e( 'Configure and use this method instead', 'wp-2fa' ); ?>"><?php esc_html_e( 'Submit', 'wp-2fa' ); ?></button> |
| 550 | </div> |
| 551 | <?php |
| 552 | } |
| 553 | ?> |
| 554 | </fieldset> |
| 555 | <div class="wp2fa-setup-actions"></div> |
| 556 | </form> |
| 557 | <?php |
| 558 | } |
| 559 | |
| 560 | /** |
| 561 | * Step Save: `Choose Method` |
| 562 | */ |
| 563 | private function wp_2fa_step_user_choose_method_save() { |
| 564 | // Check nonce. |
| 565 | check_admin_referer( 'wp2fa-step-choose-method' ); |
| 566 | |
| 567 | // Grab current user. |
| 568 | $user = wp_get_current_user(); |
| 569 | |
| 570 | // Add our enabled methods to the user metadata. |
| 571 | if ( isset( $_POST['wp_2fa_enabled_methods'] ) ) { |
| 572 | $next = add_query_arg( 'enabled_methods', sanitize_text_field( wp_unslash( $_POST['wp_2fa_enabled_methods'] ) ), $this->get_next_step() ); |
| 573 | wp_safe_redirect( esc_url_raw( $next ) ); |
| 574 | } |
| 575 | |
| 576 | exit(); |
| 577 | } |
| 578 | |
| 579 | /** |
| 580 | * Step View: `Setup Authenticator` |
| 581 | */ |
| 582 | private function wp_2fa_step_setup_authenticator() { |
| 583 | // Grab current user. |
| 584 | $user = wp_get_current_user(); |
| 585 | |
| 586 | // Grab key from user meta. |
| 587 | $key = Authentication::get_user_totp_key( $user->ID ); |
| 588 | $enabled_method = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true ); |
| 589 | |
| 590 | // If no key is present, lets make one. |
| 591 | if ( empty( $key ) ) { |
| 592 | $key = Authentication::generate_key(); |
| 593 | $update = update_user_meta( $user->ID, 'wp_2fa_totp_key', $key ); |
| 594 | } |
| 595 | |
| 596 | // Setup site information, used when generating our QR code. |
| 597 | $site_name = get_bloginfo( 'name', 'display' ); |
| 598 | $totp_title = apply_filters( 'wp_2fa_totp_title', $site_name . ':' . $user->user_login, $user ); |
| 599 | |
| 600 | // Now lets grab the users enabled 2fa methods. |
| 601 | $get_array = filter_input_array( INPUT_GET ); |
| 602 | $selected_method = ''; |
| 603 | |
| 604 | if ( isset( $_REQUEST['enabled_method'] ) ) { |
| 605 | $selected_method = $_REQUEST['enabled_method']; |
| 606 | } elseif ( isset( $get_array['enabled_methods'] ) ) { |
| 607 | $selected_method = $get_array['enabled_methods']; |
| 608 | } else { |
| 609 | $available_methods = UserUtils::get_2fa_methods_available_to_user( $user ); |
| 610 | $selected_method = $available_methods[0]; |
| 611 | } |
| 612 | |
| 613 | // Create a nonce incase we want to reset the key. |
| 614 | $nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . $user->ID ); |
| 615 | |
| 616 | // Grab notices. |
| 617 | $notices = get_user_meta( $user->ID, self::NOTICES_META_KEY, true ); |
| 618 | |
| 619 | if ( ! isset( $notices['error'] ) && empty( $notices['error'] ) ) { |
| 620 | $is_active = 'active'; |
| 621 | $is_active2 = ''; |
| 622 | } else { |
| 623 | $is_active = ''; |
| 624 | $is_active2 = 'active'; |
| 625 | } |
| 626 | |
| 627 | // TOTP is enabled for the user, so lets display the relevant steps. |
| 628 | // Here we wrap each "sub step" (a step within a step) in .tep-setting-wrapper, and nudge to next "sub step" with next_step_setting button. |
| 629 | if ( 'totp' === $selected_method ) { |
| 630 | ?> |
| 631 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active ); ?>" data-step-title="<?php esc_html_e( 'Download authenticator', 'wp-2fa' ); ?>"> |
| 632 | <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3> |
| 633 | <div class="option-pill hide-overflow"> |
| 634 | <img class="qr-code" src="<?php echo esc_url( Authentication::get_google_qr_code( $totp_title, $key, $site_name ) ); ?>" id="wp-2fa-totp-qrcode" /> |
| 635 | <ol> |
| 636 | <li><?php esc_html_e( 'Download the app of your choice', 'wp-2fa' ); ?></li> |
| 637 | <li><?php esc_html_e( 'Scan the QR code to the right (or above if on mobile).', 'wp-2fa' ); ?></li> |
| 638 | </ol> |
| 639 | <p><?php esc_html_e( 'Otherwise, select Enter a provided key and type in the key below:', 'wp-2fa' ); ?></p> |
| 640 | <code class="app-key"><?php echo esc_html( $key ); ?></code> |
| 641 | </div> |
| 642 | |
| 643 | <h4><?php esc_html_e( 'For detailed guides for your desired app, click below.', 'wp-2fa' ); ?></h4> |
| 644 | <div class="apps-wrapper"> |
| 645 | <?php foreach (Authentication::getApps() as $app): ?> |
| 646 | <a href="https://www.wpwhitesecurity.com/support/kb/configuring-2fa-apps/#<?php $app['hash']; ?>" target="_blank" class="app-logo"><img src="<?php echo esc_url( WP_2FA_URL . '/dist/images/' . $app['logo'] ); ?>"></a> |
| 647 | <?php endforeach; ?> |
| 648 | </div> |
| 649 | <div class="wp2fa-setup-actions"> |
| 650 | <button class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'I\'m Ready', 'wp-2fa' ); ?>"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></button> |
| 651 | </div> |
| 652 | </div> |
| 653 | |
| 654 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active2 ); ?>" data-step-title="<?php esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>"> |
| 655 | <form method="post" class="wp2fa-setup-form align-center" autocomplete="off"> |
| 656 | <?php wp_nonce_field( 'wp2fa-step-login' ); ?> |
| 657 | <h3><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h3> |
| 658 | <p><?php esc_html_e( 'Please type in the one-time code from your Google Authenticator app to finalize the setup.', 'wp-2fa' ); ?></p> |
| 659 | <fieldset> |
| 660 | <label for="2fa-totp-authcode"> |
| 661 | <input type="tel" name="wp-2fa-totp-authcode" id="wp-2fa-totp-authcode" class="input" value="" size="20" pattern="[0-9]*" placeholder="<?php esc_html_e( 'Authentication Code', 'wp-2fa' ); ?>"/> |
| 662 | </label> |
| 663 | </fieldset> |
| 664 | <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" /> |
| 665 | <div class="wp2fa-setup-actions"> |
| 666 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'Finish', 'wp-2fa' ); ?>"><?php esc_html_e( 'Finish', 'wp-2fa' ); ?></button> |
| 667 | </div> |
| 668 | </form> |
| 669 | </div> |
| 670 | |
| 671 | <?php |
| 672 | // Display any error notices if they are available. |
| 673 | if ( isset( $notices['error'] ) && ! empty( $notices['error'] ) ) { |
| 674 | foreach ( $notices['error'] as $notice ) { |
| 675 | echo '<p class="description error">' . wp_kses_post( $notice ) . '</p>'; |
| 676 | } |
| 677 | } |
| 678 | } elseif ( 'email' === $selected_method ) { |
| 679 | $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' ); |
| 680 | ?> |
| 681 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active ); ?>" data-step-title="<?php esc_html_e( 'Configure email', 'wp-2fa' ); ?>"> |
| 682 | <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3> |
| 683 | <p> |
| 684 | <?php esc_html_e( 'Please select the email address where the one-time code should be sent:', 'wp-2fa' ); ?> |
| 685 | </p> |
| 686 | <fieldset> |
| 687 | <div class="option-pill"> |
| 688 | <label for="use_wp_email"> |
| 689 | <input type="radio" name="wp_2fa_email_address" id="use_wp_email" value="<?php echo esc_attr( $user->user_email ); ?>" checked> |
| 690 | <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> |
| 691 | </label> |
| 692 | </div> |
| 693 | <div class="option-pill"> |
| 694 | <label for="use_custom_email"> |
| 695 | <input type="radio" name="wp_2fa_email_address" id="use_custom_email" value="use_custom_email"> |
| 696 | <span><?php esc_html_e( 'Use a different email address:', 'wp-2fa' ); ?></span> |
| 697 | <input type="email" name="custom-email-address" id="custom-email-address" class="input" value="" placeholder="<?php esc_html_e( 'Email address', 'wp-2fa' ); ?>"/> |
| 698 | </label> |
| 699 | </div> |
| 700 | </fieldset> |
| 701 | <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> |
| 702 | <div class="wp2fa-setup-actions"> |
| 703 | <button 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 ); ?>"><?php esc_html_e( 'I\'m Ready', 'wp-2fa' ); ?></button> |
| 704 | </div> |
| 705 | </div> |
| 706 | |
| 707 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active2 ); ?>" data-step-title="<?php esc_html_e( 'Verify configuration', 'wp-2fa' ); ?>"> |
| 708 | <form method="post" class="wp2fa-setup-form align-center" autocomplete="off"> |
| 709 | <?php wp_nonce_field( 'wp2fa-step-login' ); ?> |
| 710 | <h3><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h3> |
| 711 | <p><?php esc_html_e( 'Please type in the one-time code sent to your email address to finalize the setup.', 'wp-2fa' ); ?></p> |
| 712 | <fieldset> |
| 713 | <label for="2fa-email-authcode"> |
| 714 | <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*" placeholder="<?php esc_html_e( 'Authentication Code', 'wp-2fa' ); ?>"/> |
| 715 | </label> |
| 716 | </fieldset> |
| 717 | |
| 718 | <input type="hidden" name="wp-2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" /> |
| 719 | <div class="wp2fa-setup-actions"> |
| 720 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'Finish', 'wp-2fa' ); ?>"><?php esc_html_e( 'Finish', 'wp-2fa' ); ?></button> |
| 721 | <a href="#" class="button button-secondary resend-email-code" data-trigger-setup-email data-user-id="<?php echo esc_attr( $user->ID ); ?>" data-nonce="<?php echo esc_attr( $setupnonce ); ?>"> |
| 722 | <span class="resend-inner"><?php esc_html_e( 'Send me another code', 'wp-2fa' ); ?></span> |
| 723 | </a> |
| 724 | </div> |
| 725 | </form> |
| 726 | </div> |
| 727 | <?php |
| 728 | // Display any error notices if they are available. |
| 729 | if ( isset( $notices['error'] ) && ! empty( $notices['error'] ) ) { |
| 730 | foreach ( $notices['error'] as $notice ) { |
| 731 | echo '<p class="description error">' . wp_kses_post( $notice ) . '</p>'; |
| 732 | } |
| 733 | } |
| 734 | } |
| 735 | } |
| 736 | |
| 737 | /** |
| 738 | * Step Save: `Setup Authenticator` |
| 739 | */ |
| 740 | private function wp_2fa_step_setup_authenticator_save() { |
| 741 | // Check nonce. |
| 742 | check_admin_referer( 'wp2fa-step-login' ); |
| 743 | |
| 744 | // Grab current user. |
| 745 | $user = wp_get_current_user(); |
| 746 | |
| 747 | // Setup some empty arrays which will may fill later, should an error arise along the way. |
| 748 | $notices = array(); |
| 749 | $errors = array(); |
| 750 | |
| 751 | // Grab key from the $_POST. |
| 752 | if ( isset( $_POST['wp-2fa-totp-key'] ) ) { |
| 753 | $current_key = sanitize_text_field( wp_unslash( $_POST['wp-2fa-totp-key'] ) ); |
| 754 | } |
| 755 | |
| 756 | // Grab authcode and ensure its a number. |
| 757 | if ( isset( $_POST['wp-2fa-totp-authcode'] ) ) { |
| 758 | $_POST['wp-2fa-totp-authcode'] = (int) $_POST['wp-2fa-totp-authcode']; |
| 759 | } |
| 760 | |
| 761 | // Check if we are dealing with totp or email, if totp validate and store a new secret key. |
| 762 | if ( ! empty( $_POST['wp-2fa-totp-authcode'] ) && ! empty( $current_key ) ) { |
| 763 | if ( Authentication::is_valid_key( $current_key ) || ! is_numeric( $_POST['wp-2fa-totp-authcode'] ) ) { |
| 764 | if ( ! Authentication::is_valid_authcode( $current_key, sanitize_text_field( wp_unslash( $_POST['wp-2fa-totp-authcode'] ) ) ) ) { |
| 765 | $errors[] = esc_html__( 'Invalid Two Factor Authentication code.', 'wp-2fa' ); |
| 766 | } |
| 767 | } else { |
| 768 | $errors[] = esc_html__( 'Invalid Two Factor Authentication secret key.', 'wp-2fa' ); |
| 769 | } |
| 770 | |
| 771 | // If its not totp, is it email. |
| 772 | } elseif ( ! empty( $_POST['wp-2fa-email-authcode'] ) ) { |
| 773 | if ( ! Authentication::validate_token( $user->ID, sanitize_text_field( wp_unslash( $_POST['wp-2fa-email-authcode'] ) ) ) ) { |
| 774 | $errors[] = __( 'Invalid Email Authentication code.', 'wp-2fa' ); |
| 775 | } |
| 776 | } else { |
| 777 | $errors[] = __( 'Please enter the code to finalize the 2FA setup.', 'wp-2fa' ); |
| 778 | } |
| 779 | |
| 780 | if ( ! empty( $errors ) ) { |
| 781 | $notices['error'] = $errors; |
| 782 | } |
| 783 | |
| 784 | if ( ! empty( $notices ) ) { |
| 785 | update_user_meta( $user->ID, self::NOTICES_META_KEY, $notices ); |
| 786 | } |
| 787 | |
| 788 | // If no errors found, lets continue to next step and clear the notices, should any be present from previous attempts. |
| 789 | if ( empty( $notices ) ) { |
| 790 | if ( isset( $_POST['use_wp_email'] ) ) { |
| 791 | update_user_meta( $user->ID, 'wp_2fa_nominated_email_address', $user->user_email ); |
| 792 | } elseif ( isset( $_POST['use_custom_email'] ) && isset( $_POST['custom-email-address'] ) ) { |
| 793 | update_user_meta( $user->ID, 'wp_2fa_nominated_email_address', sanitize_email( wp_unslash( $_POST['custom-email-address'] ) ) ); |
| 794 | } |
| 795 | |
| 796 | // Now lets grab the users enabled 2fa methods. |
| 797 | $get_array = filter_input_array( INPUT_GET ); |
| 798 | $available_methods = UserUtils::get_2fa_methods_available_to_user( $user ); |
| 799 | $selected_method = ( isset( $get_array['enabled_methods'] ) ) ? $get_array['enabled_methods'] : $available_methods[0]; |
| 800 | // Check its one of our options. |
| 801 | if ( 'totp' === $selected_method || 'email' === $selected_method ) { |
| 802 | update_user_meta( $user->ID, 'wp_2fa_enabled_methods', sanitize_text_field( wp_unslash( $selected_method ) ) ); |
| 803 | UserProfile::delete_expire_and_enforced_keys( $user->ID ); |
| 804 | } |
| 805 | |
| 806 | wp_safe_redirect( esc_url_raw( $this->get_next_step() ) ); |
| 807 | exit(); |
| 808 | } |
| 809 | } |
| 810 | |
| 811 | /** |
| 812 | * Step View: `Finish` |
| 813 | */ |
| 814 | private function wp_2fa_step_finish() { |
| 815 | |
| 816 | $user = wp_get_current_user(); |
| 817 | $redirect = get_edit_profile_url( $user->ID ); |
| 818 | $user_type = UserUtils::determine_user_2fa_status( $user ); |
| 819 | |
| 820 | // Detmine if this is the initial setup (upon plugin activation). |
| 821 | $get_array = filter_input_array( INPUT_GET ); |
| 822 | $is_initial_setup = ( isset( $get_array['is_initial_setup'] ) ) ? true : false; |
| 823 | |
| 824 | // This is admin setting up the plugin for the 1st time, so lets allow them to continue to setting up the plugins options. |
| 825 | if ( $is_initial_setup ) : ?> |
| 826 | |
| 827 | <h3><?php esc_html_e( 'Your website just got more secure!', 'wp-2fa' ); ?></h3> |
| 828 | <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> |
| 829 | <p><?php esc_html_e( 'You can exit this wizard now or continue to configure the plugin’s general settings. ', 'wp-2fa' ); ?></p> |
| 830 | <form method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 831 | <?php wp_nonce_field( 'wp2fa-step-finish' ); ?> |
| 832 | <div class="wp2fa-setup-actions"> |
| 833 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'Continue & configure the settings', 'wp-2fa' ); ?>"> |
| 834 | <?php esc_html_e( 'Continue & configure the settings', 'wp-2fa' ); ?> |
| 835 | </button> |
| 836 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary"> |
| 837 | <?php esc_html_e( 'Close wizard, I’ll configure them later', 'wp-2fa' ); ?> |
| 838 | </a> |
| 839 | </div> |
| 840 | </form> |
| 841 | <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> |
| 842 | |
| 843 | <?php else : ?> |
| 844 | |
| 845 | <h3><?php esc_html_e( 'Your login just got more secure', 'wp-2fa' ); ?></h3> |
| 846 | <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> |
| 847 | <?php if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) { ?> |
| 848 | <p><?php esc_html_e( 'You can exit this wizard now or continue to create backup codes.', 'wp-2fa' ); ?></p> |
| 849 | <?php } ?> |
| 850 | <form method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 851 | <?php wp_nonce_field( 'wp2fa-step-finish' ); ?> |
| 852 | <div class="wp2fa-setup-actions"> |
| 853 | <?php if ( in_array( 'user_needs_to_setup_backup_codes', $user_type, true ) ) { ?> |
| 854 | <a class="button button-primary" href="<?php echo esc_url( admin_url( 'options-general.php?page=wp-2fa-setup¤t-step=backup_codes' ) ); ?>"> |
| 855 | <?php esc_html_e( 'Continue & configure backup codes', 'wp-2fa' ); ?> |
| 856 | </a> |
| 857 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary"> |
| 858 | <?php esc_html_e( 'Close wizard, I’ll configure them later', 'wp-2fa' ); ?> |
| 859 | </a> |
| 860 | <?php } else { ?> |
| 861 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary"> |
| 862 | <?php esc_html_e( 'Close wizard', 'wp-2fa' ); ?> |
| 863 | </a> |
| 864 | <?php } ?> |
| 865 | </div> |
| 866 | </form> |
| 867 | |
| 868 | <?php endif; |
| 869 | } |
| 870 | |
| 871 | /** |
| 872 | * Step Save: `Finish` |
| 873 | */ |
| 874 | private function wp_2fa_step_finish_save() { |
| 875 | // Verify nonce. |
| 876 | check_admin_referer( 'wp2fa-step-finish' ); |
| 877 | wp_safe_redirect( esc_url_raw( $this->get_next_step() ) ); |
| 878 | exit(); |
| 879 | } |
| 880 | |
| 881 | /** |
| 882 | * Step View: `Finish` |
| 883 | */ |
| 884 | private function wp_2fa_step_backup_codes() { |
| 885 | // Grab current user. |
| 886 | $user = wp_get_current_user(); |
| 887 | $roles = (array) $user->roles; |
| 888 | // Create a nonce for use in ajax call to generate codes. |
| 889 | $nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . $user->ID ); |
| 890 | |
| 891 | $redirect = get_edit_user_link( $user->ID ); |
| 892 | ?> |
| 893 | <div class="step-setting-wrapper active" data-step-title="<?php esc_html_e( 'Generate codes', 'wp-2fa' ); ?>"> |
| 894 | <h3><?php esc_html_e( 'Generate backup codes', 'wp-2fa' ); ?></h3> |
| 895 | <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> |
| 896 | |
| 897 | <form method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 898 | <?php wp_nonce_field( 'wp2fa-step-finish' ); ?> |
| 899 | <div class="wp2fa-setup-actions"> |
| 900 | <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 ); ?>"> |
| 901 | <?php esc_html_e( 'Generate backup codes', 'wp-2fa' ); ?> |
| 902 | </button> |
| 903 | <a href="<?php echo esc_url( $redirect ); ?>" class="button button-secondary" type="submit" name="save_step" value="<?php esc_attr_e( 'I’ll generate them later', 'wp-2fa' ); ?>"> |
| 904 | <?php esc_html_e( 'I’ll generate them later', 'wp-2fa' ); ?> |
| 905 | </a> |
| 906 | </div> |
| 907 | </form> |
| 908 | </div> |
| 909 | |
| 910 | <div class="step-setting-wrapper align-center" data-step-title="<?php esc_html_e( 'Your backup codes', 'wp-2fa' ); ?>"> |
| 911 | <h3><?php esc_html_e( 'Backup codes generated', 'wp-2fa' ); ?></h3> |
| 912 | <p><?php esc_html_e( 'Here are your backup codes:', 'wp-2fa' ); ?></p> |
| 913 | <code id="backup-codes-wrapper"></code> |
| 914 | <div class="wp2fa-setup-actions"> |
| 915 | <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() ); ?>"> |
| 916 | <?php esc_html_e( 'Download', 'wp-2fa' ); ?> |
| 917 | </button> |
| 918 | <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() ); ?>"> |
| 919 | <?php esc_html_e( 'Print', 'wp-2fa' ); ?> |
| 920 | </button> |
| 921 | </div> |
| 922 | </div> |
| 923 | <style> |
| 924 | .close-wizard-link { display: none; } |
| 925 | </style> |
| 926 | <?php |
| 927 | } |
| 928 | |
| 929 | /** |
| 930 | * Step Save: `Finish` |
| 931 | */ |
| 932 | private function wp_2fa_step_backup_codes_save() { |
| 933 | // Verify nonce. |
| 934 | check_admin_referer( 'wp2fa-step-finish' ); |
| 935 | } |
| 936 | |
| 937 | /** |
| 938 | * Step View: `Choose Methods` |
| 939 | */ |
| 940 | private function wp_2fa_step_global_2fa_methods() { |
| 941 | $enforced_roles = trim( WP2FA::get_wp2fa_setting( 'enforced_roles' ) ); |
| 942 | $enforced_users = trim( WP2FA::get_wp2fa_setting( 'enforced_users' ) ); |
| 943 | $excluded_users = trim( WP2FA::get_wp2fa_setting( 'excluded_users' ) ); |
| 944 | $excluded_roles = trim( WP2FA::get_wp2fa_setting( 'excluded_roles' ) ); |
| 945 | ?> |
| 946 | <form method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 947 | <?php wp_nonce_field( 'wp2fa-step-choose-method' ); ?> |
| 948 | <div class="step-setting-wrapper active" data-step-title="<?php esc_html_e( 'Choose 2FA methods', 'wp-2fa' ); ?>"> |
| 949 | <h3><?php esc_html_e( 'Which two-factor authentication methods can your users use on this website?', 'wp-2fa' ); ?></h3> |
| 950 | <p><?php esc_html_e( 'When you disable one of the below 2FA methods none of your users can use it.', 'wp-2fa' ); ?></p> |
| 951 | <fieldset> |
| 952 | <div class="option-pill"> |
| 953 | <label for="basic"> |
| 954 | <input id="basic" name="wp_2fa_settings[enable_totp]" type="checkbox" value="enable_totp" |
| 955 | <?php checked( 'enable_totp', WP2FA::get_wp2fa_setting( 'enable_totp' ), true ); ?> |
| 956 | > |
| 957 | <?php esc_html_e( 'One-time code generated with your app of choice (most reliable and secure)', 'wp-2fa' ); ?> |
| 958 | </label> |
| 959 | <?php |
| 960 | printf( '<p class="description">%1$s <a href="https://www.wpwhitesecurity.com/support/kb/configuring-2fa-apps/" target="_blank">%2$s</a> %3$s</p>', esc_html__( 'Note: This method requires you to install one of the following 2FA apps: Google Authenticator, FreeOTP, Microsoft Authenticator, Duo Security, Authy, LastPass and Okta Verify. All of these apps are free and can be downloaded from the Google Play and Apple Appstore. Read our guides on', 'wp-2fa' ), esc_html__( 'our knowledge base', 'wp-2fa' ), esc_html__( 'for more information on how to setup these apps.', 'wp-2fa' ) ); |
| 961 | ?> |
| 962 | </p> |
| 963 | </div> |
| 964 | <div class="option-pill"> |
| 965 | <label for="geek"> |
| 966 | <input id="geek" name="wp_2fa_settings[enable_email]" type="checkbox" value="enable_email" |
| 967 | <?php checked( WP2FA::get_wp2fa_setting( 'enable_email' ), 'enable_email' ); ?> |
| 968 | > |
| 969 | <?php esc_html_e( 'One-time code sent to user over email', 'wp-2fa' ); ?> |
| 970 | </label> |
| 971 | </div> |
| 972 | </fieldset> |
| 973 | <div class="wp2fa-setup-actions"> |
| 974 | <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a> |
| 975 | </div> |
| 976 | </div> |
| 977 | <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( '2FA policy', 'wp-2fa' ); ?>"> |
| 978 | <h3><?php esc_html_e( 'Do you want to enforce 2FA for some, or all the users?', 'wp-2fa' ); ?></h3> |
| 979 | <p><?php esc_html_e( 'When you enforce 2FA the users will be prompted to configure 2FA the next time they login. Users have a grace period for configuring 2FA. You can configure the grace period and also exclude user(s) or role(s) in this settings page.', 'wp-2fa' ); ?></p> |
| 980 | <fieldset class="contains-hidden-inputs"> |
| 981 | <label for="all-users"> |
| 982 | <input type="radio" name="wp_2fa_settings[enforcement-policy]" id="all-users" value="all-users" |
| 983 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcement-policy' ), 'all-users' ); ?> |
| 984 | > |
| 985 | <span><?php esc_html_e( 'All users', 'wp-2fa' ); ?></span> |
| 986 | </label> |
| 987 | <br/> |
| 988 | |
| 989 | <?php if ( WP2FA::is_this_multisite() ): ?> |
| 990 | <label for="superadmins-only"> |
| 991 | <input type="radio" name="wp_2fa_settings[enforcement-policy]" id="superadmins-only" value="superadmins-only" |
| 992 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcement-policy' ), 'superadmins-only' ); ?> /> |
| 993 | <span><?php esc_html_e( 'Only super admins', 'wp-2fa' ); ?></span> |
| 994 | </label> |
| 995 | <br/> |
| 996 | <?php endif; ?> |
| 997 | |
| 998 | <label for="certain-roles-only"> |
| 999 | <input type="radio" name="wp_2fa_settings[enforcement-policy]" id="certain-roles-only" value="certain-roles-only" |
| 1000 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcement-policy' ), 'certain-roles-only' ); ?> |
| 1001 | data-unhide-when-checked=".certain-roles-only-inputs, .certain-users-only-inputs"> |
| 1002 | <span><?php esc_html_e( 'Only for specific users and roles', 'wp-2fa' ); ?></span> |
| 1003 | </label> |
| 1004 | <fieldset class="hidden certain-users-only-inputs"> |
| 1005 | <br/> |
| 1006 | <input type="text" id="enforced_users_search" placeholder="Search users"> |
| 1007 | <input type="hidden" id="enforced_users" name="wp_2fa_settings[enforced_users]" value="<?php echo esc_attr( $enforced_users ); ?>"> |
| 1008 | <div id="enforced_users_buttons"></div> |
| 1009 | </fieldset> |
| 1010 | <fieldset class="hidden certain-roles-only-inputs"> |
| 1011 | <br/> |
| 1012 | <input type="text" id="enforced_roles_search" placeholder="Search roles"> |
| 1013 | <input type="hidden" id="enforced_roles" name="wp_2fa_settings[enforced_roles]" value="<?php echo esc_attr( $enforced_roles ); ?>"> |
| 1014 | <div id="enforced_roles_buttons"></div> |
| 1015 | </fieldset> |
| 1016 | |
| 1017 | </label> |
| 1018 | |
| 1019 | <br/> |
| 1020 | <label for="do-not-enforce"> |
| 1021 | <input type="radio" name="wp_2fa_settings[enforcement-policy]" id="do-not-enforce" value="do-not-enforce" |
| 1022 | <?php checked( WP2FA::get_wp2fa_setting( 'enforcement-policy' ), 'do-not-enforce' ); ?> |
| 1023 | > |
| 1024 | <span><?php esc_html_e( 'Do not enforce 2FA on any users', 'wp-2fa' ); ?></span> |
| 1025 | </label> |
| 1026 | <br/> |
| 1027 | </fieldset> |
| 1028 | <div class="wp2fa-setup-actions"> |
| 1029 | <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a> |
| 1030 | </div> |
| 1031 | </div> |
| 1032 | <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Exclude users', 'wp-2fa' ); ?>"> |
| 1033 | <h3><?php esc_html_e( 'Do you want to exclude any users or roles from 2FA?', 'wp-2fa' ); ?></h3> |
| 1034 | <p><?php esc_html_e( 'If you are enforcing 2FA on all users but for some reason you would like to exclude individual user(s) or users with a specific role, you can exclude them below', 'wp-2fa' ); ?></p> |
| 1035 | <fieldset> |
| 1036 | <div class="option-pill"> |
| 1037 | <label for="basic"><?php esc_html_e( 'Exclude the following users', 'wp-2fa' ); ?> |
| 1038 | <input type="text" class="input wide" id="excluded_users_search" placeholder="<?php esc_html_e( 'Search user name', 'wp-2fa' ); ?>"> |
| 1039 | <input type="hidden" id="excluded_users" name="wp_2fa_settings[excluded_users]" value="<?php echo esc_attr( $excluded_users ); ?>"> |
| 1040 | <div id="excluded_users_buttons"></div> |
| 1041 | </label> |
| 1042 | <label for="geek"><?php esc_html_e( 'Exclude the following roles', 'wp-2fa' ); ?> |
| 1043 | <input type="text" class="input wide" id="excluded_roles_search" placeholder="<?php esc_html_e( 'Search roles', 'wp-2fa' ); ?>"> |
| 1044 | <input type="hidden" id="excluded_roles" name="wp_2fa_settings[excluded_roles]" value="<?php echo esc_attr( $excluded_roles ); ?>"> |
| 1045 | <div id="excluded_roles_buttons"></div> |
| 1046 | </label> |
| 1047 | </div> |
| 1048 | </fieldset> |
| 1049 | <div class="wp2fa-setup-actions"> |
| 1050 | <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a> |
| 1051 | </div> |
| 1052 | </div> |
| 1053 | |
| 1054 | <?php if ( WP2FA::is_this_multisite() ) : ?> |
| 1055 | <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Exclude sites', 'wp-2fa' ); ?>"> |
| 1056 | <h3><?php esc_html_e( 'Do you want to exclude all the users of a site from 2FA?', 'wp-2fa' ); ?></h3> |
| 1057 | <p><?php esc_html_e( 'If you are enforcing 2FA on all users but for some reason you do not want to enforce it on a specific sub site, specify the sub site name below:', 'wp-2fa' ); ?></p> |
| 1058 | <fieldset> |
| 1059 | <div class="option-pill"> |
| 1060 | <label for="excluded_sites_search"><?php esc_html_e( 'Exclude the following sites', 'wp-2fa' ); ?> |
| 1061 | <input type="text" id="excluded_sites_search" placeholder="Search network"> |
| 1062 | <input type="hidden" id="excluded_sites" name="wp_2fa_settings[excluded_sites]" |
| 1063 | value="<?php echo trim( sanitize_text_field( WP2FA::get_wp2fa_setting( 'excluded_sites' ) ) ); ?>"> |
| 1064 | <div id="excluded_sites_buttons"></div> |
| 1065 | </label> |
| 1066 | </div> |
| 1067 | </fieldset> |
| 1068 | <div class="wp2fa-setup-actions"> |
| 1069 | <a class="button button-primary" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a> |
| 1070 | </div> |
| 1071 | </div> |
| 1072 | <?php endif; ?> |
| 1073 | |
| 1074 | <?php |
| 1075 | $grace_period = (int) WP2FA::get_wp2fa_setting( 'grace-period' ); |
| 1076 | $testing = get_option( 'wp_2fa_test_grace' ); |
| 1077 | if ( '1' === $testing ) { |
| 1078 | $grace_max = 600; |
| 1079 | } else { |
| 1080 | $grace_max = 10; |
| 1081 | } |
| 1082 | ?> |
| 1083 | |
| 1084 | <div class="step-setting-wrapper" data-step-title="<?php esc_html_e( 'Grace period', 'wp-2fa' ); ?>"> |
| 1085 | <h3><?php esc_html_e( 'How long should the grace period for your users be?', 'wp-2fa' ); ?></h3> |
| 1086 | <p><?php esc_html_e( 'When you configure the 2FA policies and require users to configure 2FA, they can either have a grace period to configure 2FA, or can be required to configure 2FA before the next time they login. Choose which method you\'d like to use:', 'wp-2fa' ); ?></p> |
| 1087 | <fieldset class="contains-hidden-inputs"> |
| 1088 | <label for="no-grace-period"> |
| 1089 | <input type="radio" name="wp_2fa_settings[grace-policy]" id="no-grace-period" value="no-grace-period" |
| 1090 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-policy' ), 'no-grace-period' ); ?> |
| 1091 | > |
| 1092 | <span><?php esc_html_e( 'Users have to configure 2FA straight away.', 'wp-2fa' ); ?></span> |
| 1093 | </label> |
| 1094 | |
| 1095 | <br/> |
| 1096 | <label for="use-grace-period"> |
| 1097 | <input type="radio" name="wp_2fa_settings[grace-policy]" id="use-grace-period" value="use-grace-period" |
| 1098 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-policy' ), 'use-grace-period' ); ?> |
| 1099 | data-unhide-when-checked=".grace-period-inputs"> |
| 1100 | <span><?php esc_html_e( 'Give users a grace period to configure 2FA', 'wp-2fa' ); ?></span> |
| 1101 | </label> |
| 1102 | <br> |
| 1103 | <fieldset class="grace-period-inputs"> |
| 1104 | <br/> |
| 1105 | <input type="number" id="grace-period" name="wp_2fa_settings[grace-period]" value="<?php echo esc_attr( $grace_period ); ?>" min="1" max="<?php echo esc_attr( $grace_max ); ?>"> |
| 1106 | <label class="radio-inline"> |
| 1107 | <input class="js-nested" type="radio" name="wp_2fa_settings[grace-period-denominator]" value="hours" |
| 1108 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-period-denominator' ), 'hours' ); ?> |
| 1109 | > |
| 1110 | <?php esc_html_e( 'Hours', 'wp-2fa' ); ?> |
| 1111 | </label> |
| 1112 | <label class="radio-inline"> |
| 1113 | <input class="js-nested" type="radio" name="wp_2fa_settings[grace-period-denominator]" value="days" |
| 1114 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-period-denominator' ), 'days' ); ?> |
| 1115 | > |
| 1116 | <?php esc_html_e( 'Days', 'wp-2fa' ); ?> |
| 1117 | </label> |
| 1118 | <?php |
| 1119 | $testing = get_option( 'wp_2fa_test_grace' ); |
| 1120 | if ( '1' === $testing ) { |
| 1121 | ?> |
| 1122 | <label class="js-nested" class="radio-inline"> |
| 1123 | <input type="radio" name="wp_2fa_settings[grace-period-denominator]" value="seconds" |
| 1124 | <?php checked( WP2FA::get_wp2fa_setting( 'grace-period-denominator' ), 'seconds' ); ?> |
| 1125 | > |
| 1126 | <?php esc_html_e( 'Seconds', 'wp-2fa' ); ?> |
| 1127 | </label> |
| 1128 | <?php |
| 1129 | } |
| 1130 | ?> |
| 1131 | <p><?php esc_html_e( 'Note: If users do not configure it within the configured stipulated time, their account will be locked and have to be unlocked manually.', 'wp-2fa' ); ?></p> |
| 1132 | </fieldset> |
| 1133 | </fieldset> |
| 1134 | <div class="wp2fa-setup-actions"> |
| 1135 | <a class="button button-primary continue-wizard hidden" name="next_step_setting" value="<?php esc_attr_e( 'Continue Setup', 'wp-2fa' ); ?>"><?php esc_html_e( 'Continue Setup', 'wp-2fa' ); ?></a> |
| 1136 | <button class="button button-primary save-wizard" type="submit" name="save_step" value="<?php esc_attr_e( 'All done', 'wp-2fa' ); ?>"><?php esc_html_e( 'All done', 'wp-2fa' ); ?></button> |
| 1137 | </div> |
| 1138 | </div> |
| 1139 | |
| 1140 | <div class="step-setting-wrapper hidden" data-step-title="<?php esc_html_e( 'Notify users', 'wp-2fa' ); ?>"> |
| 1141 | <h3><?php esc_html_e( 'Do you want to notify users now?', 'wp-2fa' ); ?></h3> |
| 1142 | <p><?php esc_html_e( 'When you require users to configure 2FA via policies, the plugin notifies the user with an email and a message in the WordPress dashboard. Do you want to send the emails now?', 'wp-2fa' ); ?></p> |
| 1143 | <fieldset> |
| 1144 | <div class="option-pill"> |
| 1145 | <label for="notify_users"> |
| 1146 | <input type="checkbox" id="notify_users" name="wp_2fa_settings[notify_users]" value="notify_users" checked> |
| 1147 | <span><?php esc_html_e( 'Notify users now.', 'wp-2fa' ); ?></span> |
| 1148 | </label> |
| 1149 | </div> |
| 1150 | |
| 1151 | </fieldset> |
| 1152 | <div class="wp2fa-setup-actions"> |
| 1153 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'All done', 'wp-2fa' ); ?>"><?php esc_html_e( 'All done', 'wp-2fa' ); ?></button> |
| 1154 | </div> |
| 1155 | </div> |
| 1156 | |
| 1157 | </form> |
| 1158 | <?php |
| 1159 | } |
| 1160 | |
| 1161 | /** |
| 1162 | * Step Save: `Choose Method` |
| 1163 | */ |
| 1164 | private function wp_2fa_step_global_2fa_methods_save() { |
| 1165 | // Check nonce. |
| 1166 | check_admin_referer( 'wp2fa-step-choose-method' ); |
| 1167 | |
| 1168 | $input = ( isset( $_POST['wp_2fa_settings'] ) ) ? wp_unslash( $_POST['wp_2fa_settings'] ) : array(); |
| 1169 | |
| 1170 | $settings_page = new SettingsPage; |
| 1171 | $sanitized_settings = $settings_page->validate_and_sanitize( $input, 'setup_wizard' ); |
| 1172 | $update_options = update_site_option( 'wp_2fa_settings', $sanitized_settings ); |
| 1173 | |
| 1174 | wp_safe_redirect( esc_url_raw( $this->get_next_step() ) ); |
| 1175 | exit(); |
| 1176 | } |
| 1177 | |
| 1178 | /** |
| 1179 | * Send email with fresh code, or to setup email 2fa. |
| 1180 | * |
| 1181 | * @param int $user_id User id we want to send the message to. |
| 1182 | * @param string $nonce The nonce. |
| 1183 | * |
| 1184 | * @return bool |
| 1185 | */ |
| 1186 | public static function send_authentication_setup_email( $user_id, $nonce = '' ) { |
| 1187 | |
| 1188 | // If we have a nonce posted, check it. |
| 1189 | if ( wp_doing_ajax() && isset( $_POST['nonce'] ) ) { |
| 1190 | $nonce_check = wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'wp-2fa-send-setup-email' ); |
| 1191 | if ( ! $nonce_check ) { |
| 1192 | return false; |
| 1193 | exit(); |
| 1194 | } |
| 1195 | } |
| 1196 | |
| 1197 | if ( isset( $_POST['user_id'] ) ) { |
| 1198 | $user = get_userdata( intval( $_POST['user_id'] ) ); |
| 1199 | } else { |
| 1200 | $user = get_userdata( $user_id ); |
| 1201 | } |
| 1202 | |
| 1203 | // Seeing as we got this far, we need to clear notices to make way for anything fresh. |
| 1204 | delete_user_meta( $user->ID, self::NOTICES_META_KEY ); |
| 1205 | |
| 1206 | // Grab email address is its provided. |
| 1207 | if ( isset( $_POST['email_address'] ) ) { |
| 1208 | $email = sanitize_email( $_POST['email_address'] ); |
| 1209 | } else { |
| 1210 | $email = sanitize_email( $user->user_email ); |
| 1211 | } |
| 1212 | |
| 1213 | if ( wp_doing_ajax() && isset( $_POST['nonce'] ) ) { |
| 1214 | update_user_meta( $user->ID, 'wp_2fa_nominated_email_address', $email ); |
| 1215 | } |
| 1216 | |
| 1217 | $enabled_email_address = get_user_meta( $user->ID, 'wp_2fa_nominated_email_address', true ); |
| 1218 | |
| 1219 | // Generate a token and setup email. |
| 1220 | $token = Authentication::generate_token( $user->ID ); |
| 1221 | $subject = wp_strip_all_tags( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'login_code_email_subject' ), $user->ID ) ); |
| 1222 | $message = wpautop( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'login_code_email_body' ), $user->ID, $token ) ); |
| 1223 | |
| 1224 | if ( ! empty( $enabled_email_address ) ) { |
| 1225 | $email_address = $enabled_email_address; |
| 1226 | } else { |
| 1227 | $email_address = $user->user_email; |
| 1228 | } |
| 1229 | |
| 1230 | return SettingsPage::send_email( $email_address, $subject, $message ); |
| 1231 | } |
| 1232 | |
| 1233 | /** |
| 1234 | * Send email to setup authentication |
| 1235 | */ |
| 1236 | public function regenerate_authentication_key() { |
| 1237 | // Grab current user. |
| 1238 | $user = wp_get_current_user(); |
| 1239 | |
| 1240 | // Delete the key and enabled methods |
| 1241 | Authentication::delete_user_totp_key( $user->ID ); |
| 1242 | $wipe_enabled_methods = delete_user_meta( $user->ID, 'wp_2fa_enabled_methods' ); |
| 1243 | |
| 1244 | $key = Authentication::generate_key(); |
| 1245 | $update = update_user_meta( $user->ID, 'wp_2fa_totp_key', $key ); |
| 1246 | |
| 1247 | $site_name = get_bloginfo( 'name', 'display' ); |
| 1248 | $totp_title = apply_filters( 'wp_2fa_totp_title', $site_name . ':' . $user->user_login, $user ); |
| 1249 | $new_qr = Authentication::get_google_qr_code( $totp_title, $key, $site_name ); |
| 1250 | |
| 1251 | wp_send_json_success( |
| 1252 | array( |
| 1253 | 'key' => $key, |
| 1254 | 'qr' => $new_qr, |
| 1255 | ) |
| 1256 | ); |
| 1257 | } |
| 1258 | |
| 1259 | /** |
| 1260 | * Step View: `Setup Authenticator` |
| 1261 | */ |
| 1262 | private function wp_2fa_step_reconfigure_authenticator() { |
| 1263 | // Grab current user |
| 1264 | $user = wp_get_current_user(); |
| 1265 | |
| 1266 | // Grab key from user meta |
| 1267 | $key = Authentication::get_user_totp_key( $user->ID ); |
| 1268 | |
| 1269 | // If no key is present, lets make one |
| 1270 | if ( empty( $key ) ) { |
| 1271 | $key = Authentication::generate_key(); |
| 1272 | $update = update_user_meta( $user->ID, 'wp_2fa_totp_key', $key ); |
| 1273 | } |
| 1274 | |
| 1275 | // Setup site information, used when generating our QR code |
| 1276 | $site_name = get_bloginfo( 'name', 'display' ); |
| 1277 | $totp_title = apply_filters( 'wp_2fa_totp_title', $site_name . ':' . $user->user_login, $user ); |
| 1278 | |
| 1279 | // Now lets grab the users enabled 2fa methods. |
| 1280 | $selected_method = get_user_meta( $user->ID, 'wp_2fa_enabled_methods', true ); |
| 1281 | |
| 1282 | // Create a nonce incase we want to reset the key |
| 1283 | $nonce = wp_create_nonce( 'wp-2fa-backup-codes-generate-json-' . $user->ID ); |
| 1284 | |
| 1285 | if ( ! isset( $notices['error'] ) && empty( $notices['error'] ) ) { |
| 1286 | $is_active = 'active'; |
| 1287 | $is_active2 = ''; |
| 1288 | } else { |
| 1289 | $is_active = ''; |
| 1290 | $is_active2 = 'active'; |
| 1291 | } |
| 1292 | |
| 1293 | // TOTP is enabled for the user, so lets display the relevant steps. |
| 1294 | // Here we wrap each "sub step" (a step within a step) in .tep-setting-wrapper, and nudge to next "sub step" with next_step_setting button. |
| 1295 | if ( ! empty( WP2FA::get_wp2fa_setting( 'enable_totp' ) ) ) { |
| 1296 | ?> |
| 1297 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active ); ?>" data-step-title="<?php esc_html_e( 'Reconfigure 2FA', 'wp-2fa' ); ?>"> |
| 1298 | <h3> |
| 1299 | <?php esc_html_e( 'Reconfigure the 2FA App', 'wp-2fa' ); ?> |
| 1300 | </h3> |
| 1301 | <p> |
| 1302 | <?php esc_html_e( 'Click the below button to reconfigure the current 2FA method. You can use this if for example, you want to change your device or 2FA app. 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' ); ?> |
| 1303 | </p> |
| 1304 | <div class="wp2fa-setup-actions"> |
| 1305 | <a href="<?php echo esc_url( admin_url( 'options-general.php?page=wp-2fa-setup¤t-step=setup_method&enabled_method=totp' ) ); ?>" class="button button-primary do-not-reload" data-trigger-reset-key data-nonce="<?php echo esc_attr( $nonce ); ?>" data-user-id="<?php echo esc_attr( $user->ID ); ?>"><?php esc_html_e( 'Reset Key', 'wp-2fa' ); ?></a> |
| 1306 | </div> |
| 1307 | </div> |
| 1308 | |
| 1309 | <?php |
| 1310 | } elseif ( ! empty( WP2FA::get_wp2fa_setting( 'enable_email' ) ) ) { |
| 1311 | $setupnonce = wp_create_nonce( 'wp-2fa-send-setup-email' ); |
| 1312 | ?> |
| 1313 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active ); ?>" data-step-title="<?php esc_html_e( 'Configure email', 'wp-2fa' ); ?>"> |
| 1314 | <h3><?php esc_html_e( 'Setup the 2FA method', 'wp-2fa' ); ?></h3> |
| 1315 | <p> |
| 1316 | <?php esc_html_e( 'Please select the email address where the one-time code should be sent:', 'wp-2fa' ); ?> |
| 1317 | </p> |
| 1318 | <fieldset> |
| 1319 | <label for="use_wp_email"> |
| 1320 | <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> |
| 1321 | <input type="email" name="custom-email-address" id="custom-email-address" class="input wide" value=""/> |
| 1322 | </label> |
| 1323 | </fieldset> |
| 1324 | <div class="wp2fa-setup-actions"> |
| 1325 | <button 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 ); ?>"><?php esc_html_e( 'Change email address', 'wp-2fa' ); ?></button> |
| 1326 | </div> |
| 1327 | </div> |
| 1328 | |
| 1329 | <div class="step-setting-wrapper <?php echo esc_attr( $is_active2 ); ?>" data-step-title="<?php esc_html_e( 'Validate email', 'wp-2fa' ); ?>"> |
| 1330 | <form method="post" class="wp2fa-setup-form" autocomplete="off"> |
| 1331 | <?php wp_nonce_field( 'wp2fa-step-login' ); ?> |
| 1332 | <h4><?php esc_html_e( 'Almost there…', 'wp-2fa' ); ?></h4> |
| 1333 | <p><?php esc_html_e( 'Please type in the one-time code sent to your email address to finalize the setup.', 'wp-2fa' ); ?></p> |
| 1334 | <fieldset> |
| 1335 | <label for="2fa-email-authcode"> |
| 1336 | <?php esc_html_e( 'Authentication Code:', 'wp-2fa' ); ?> |
| 1337 | <input type="tel" name="wp-2fa-email-authcode" id="wp-2fa-email-authcode" class="input" value="" size="20" pattern="[0-9]*" /> |
| 1338 | </label> |
| 1339 | </fieldset> |
| 1340 | |
| 1341 | <input type="hidden" name="2fa-totp-key" value="<?php echo esc_attr( $key ); ?>" /> |
| 1342 | <div class="wp2fa-setup-actions"> |
| 1343 | <button class="button button-primary" type="submit" name="save_step" value="<?php esc_attr_e( 'Finish', 'wp-2fa' ); ?>"><?php esc_html_e( 'Finish', 'wp-2fa' ); ?></button> |
| 1344 | </div> |
| 1345 | </form> |
| 1346 | </div> |
| 1347 | <?php |
| 1348 | // Display any error notices if they are available. |
| 1349 | if ( isset( $notices['error'] ) && ! empty( $notices['error'] ) ) { |
| 1350 | foreach ( $notices['error'] as $notice ) { |
| 1351 | echo '<p class="description error">' . wp_kses_post( $notice ) . '</p>'; |
| 1352 | } |
| 1353 | } |
| 1354 | } |
| 1355 | } |
| 1356 | |
| 1357 | /** |
| 1358 | * Step Save: `Setup Authenticator` |
| 1359 | */ |
| 1360 | private function wp_2fa_step_reconfigure_authenticator_save() { |
| 1361 | // Check nonce. |
| 1362 | check_admin_referer( 'wp2fa-step-login' ); |
| 1363 | // Grab current user |
| 1364 | $user = wp_get_current_user(); |
| 1365 | |
| 1366 | // Setup some empty arrays which will may fill later, should an error arise along the way. |
| 1367 | $notices = array(); |
| 1368 | $errors = array(); |
| 1369 | |
| 1370 | // Grab key from the $_POST |
| 1371 | if ( isset( $_POST['wp-2fa-totp-key'] ) ) { |
| 1372 | $current_key = sanitize_text_field( wp_unslash( $_POST['wp-2fa-totp-key'] ) ); |
| 1373 | } |
| 1374 | |
| 1375 | // Check if we are dealing with totp or email, if totp validate and store a new secret key. |
| 1376 | if ( ! empty( $_POST['wp-2fa-totp-authcode'] ) && ! empty( $current_key ) ) { |
| 1377 | if ( Authentication::is_valid_key( $current_key ) || ! is_numeric( $_POST['wp-2fa-totp-authcode'] ) ) { |
| 1378 | if ( ! Authentication::is_valid_authcode( $current_key, $_POST['wp-2fa-totp-authcode'] ) ) { |
| 1379 | $errors[] = esc_html__( 'Invalid Two Factor Authentication code.', 'wp-2fa' ); |
| 1380 | } |
| 1381 | } else { |
| 1382 | $errors[] = esc_html__( 'Invalid Two Factor Authentication secret key.', 'wp-2fa' ); |
| 1383 | } |
| 1384 | |
| 1385 | // If its not totp, is it email? |
| 1386 | } elseif ( ! empty( $_POST['wp-2fa-email-authcode'] ) ) { |
| 1387 | if ( ! Authentication::validate_token( $user->ID, $_POST['wp-2fa-email-authcode'] ) ) { |
| 1388 | $errors[] = __( 'Invalid Email Authentication code.', 'wp-2fa' ); |
| 1389 | } |
| 1390 | } else { |
| 1391 | $errors[] = __( 'Please enter the code to finalize the 2FA setup.', 'wp-2fa' ); |
| 1392 | } |
| 1393 | |
| 1394 | if ( ! empty( $errors ) ) { |
| 1395 | $notices['error'] = $errors; |
| 1396 | } |
| 1397 | |
| 1398 | if ( ! empty( $notices ) ) { |
| 1399 | update_user_meta( $user->ID, self::NOTICES_META_KEY, $notices ); |
| 1400 | delete_user_meta( $user->ID, 'wp_2fa_nominated_email_address' ); |
| 1401 | } |
| 1402 | |
| 1403 | // If no errors found, lets continue to next step and clear the notices, should any be present from previous attempts. |
| 1404 | if ( empty( $notices ) ) { |
| 1405 | wp_safe_redirect( esc_url_raw( $this->get_next_step() ) ); |
| 1406 | exit(); |
| 1407 | } |
| 1408 | } |
| 1409 | |
| 1410 | /** |
| 1411 | * 3rd Party plugins |
| 1412 | */ |
| 1413 | function wp_2fa_add_intro_step( $wizard_steps ) { |
| 1414 | $new_wizard_steps = array( |
| 1415 | 'test' => array( |
| 1416 | 'name' => __( 'Welcome to WP 2FA', 'wp-security-audit-log' ), |
| 1417 | 'content' => array( $this, 'introduction_step' ), |
| 1418 | 'save' => array( $this, 'introduction_step_save' ), |
| 1419 | 'wizard_type' => 'welcome_wizard', |
| 1420 | ), |
| 1421 | ); |
| 1422 | |
| 1423 | // combine the two arrays. |
| 1424 | $wizard_steps = $new_wizard_steps + $wizard_steps; |
| 1425 | |
| 1426 | return $wizard_steps; |
| 1427 | } |
| 1428 | |
| 1429 | private function introduction_step() { |
| 1430 | ?> |
| 1431 | <form method="post" class="wsal-setup-form"> |
| 1432 | <?php wp_nonce_field( 'wsal-step-addon' ); ?> |
| 1433 | <h3><?php esc_html_e( 'You are required to configure 2FA.', 'wp-security-audit-log' ); ?></h3> |
| 1434 | <p><?php esc_html_e( 'In order to keep this site - and your details secure, this website’s administrator requires you to enable 2FA authentication to continue.', 'wp-security-audit-log' ); ?></p> |
| 1435 | <p><?php esc_html_e( 'Two factor authentication ensures only you have access to your account by creating an added layer of security when logging in -', 'wp-security-audit-log' ); ?> <a href="https://www.wpwhitesecurity.com/two-factor-authentication-wordpress/" target="_blank"><?php esc_html_e( 'Learn more', 'wp-security-audit-log' ); ?></a></p> |
| 1436 | |
| 1437 | <div class="wsal-setup-actions"> |
| 1438 | <button class="button button-primary" |
| 1439 | type="submit" |
| 1440 | name="save_step" |
| 1441 | value="<?php esc_attr_e( 'Next', 'wp-security-audit-log' ); ?>"> |
| 1442 | <?php esc_html_e( 'Next', 'wp-security-audit-log' ); ?> |
| 1443 | </button> |
| 1444 | </div> |
| 1445 | </form> |
| 1446 | <?php |
| 1447 | } |
| 1448 | |
| 1449 | /** |
| 1450 | * Step Save: `Addons` |
| 1451 | */ |
| 1452 | private function introduction_step_save() { |
| 1453 | // Check nonce. |
| 1454 | check_admin_referer( 'wsal-step-addon' ); |
| 1455 | |
| 1456 | wp_safe_redirect( esc_url_raw( $this->get_next_step() ) ); |
| 1457 | exit(); |
| 1458 | } |
| 1459 | } |
| 1460 |