PluginProbe
Two Factor Authentication / 1.0
Two Factor Authentication v1.0
1.12.2 1.13.0 1.14.10 1.14.11 1.14.14 1.14.15 1.14.16 1.14.17 1.14.23 1.14.24 1.14.26 1.14.27 1.14.3 1.14.4 1.14.5 1.14.7 1.14.8 1.15.5 1.16.0 1.2.10 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 All 98 releases
two-factor-authentication / two-factor-login.php

two-factor-login.php in Two Factor Authentication 1.0, at two-factor-login.php

584 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Two Factor Authentication
4 Plugin URI:
5 Description: Secure your WordPress login forms with two factor authentication - including WooCommerce login forms
6 Author: David Nutbourne + David Anderson, original plugin by Oskar Hane
7 Author URI: https://www.simbahosting.co.uk
8 Version: 1.0
9 License: GPLv2 or later
10 */
11
12 define('SIMBA_TFA_TEXT_DOMAIN', 'two-factor-authentication');
13 define('SIMBA_TFA_PLUGIN_DIR', dirname( __FILE__ ));
14 define('SIMBA_TFA_PLUGIN_URL', plugins_url('', __FILE__));
15
16 class Simba_Two_Factor_Authentication {
17
18 public $version = '1.0';
19 private $php_required = '5.3';
20
21 public function __construct() {
22
23 if (file_exists(SIMBA_TFA_PLUGIN_DIR.'/premium.php')) include_once(SIMBA_TFA_PLUGIN_DIR.'/premium.php');
24
25 if (version_compare(PHP_VERSION, $this->php_required, '<' )) {
26 add_action('all_admin_notices', array($this, 'admin_notice_insufficient_php'));
27 $abort = true;
28 }
29
30 if (!function_exists('mcrypt_get_iv_size')) {
31 add_action('all_admin_notices', array($this, 'admin_notice_missing_mcrypt'));
32 $abort = true;
33 }
34
35 if (!empty($abort)) return;
36
37 add_action('wp_ajax_nopriv_simbatfa-init-otp', array($this, 'tfaInitLogin'));
38
39 add_action('wp_ajax_simbatfa_shared_ajax', array($this, 'shared_ajax'));
40
41 add_action('woocommerce_before_customer_login_form', array($this, 'woocommerce_before_customer_login_form'));
42
43 if (is_admin()) {
44 //Save settings
45 add_action('admin_init', array($this, 'check_possible_reset'));
46
47 //Add to Settings menu
48 add_action('admin_menu', array($this, 'addTwoFactorAuthAdminMenu'));
49
50 //Add settings link in plugin list
51 $plugin = plugin_basename(__FILE__);
52 add_filter("plugin_action_links_".$plugin, array($this, 'addPluginSettingsLink' ));
53
54 } else {
55 add_action('init', array($this, 'check_possible_reset'));
56 }
57
58 add_action('plugins_loaded', array($this, 'plugins_loaded'));
59
60 //Show off sync message for hotp
61 add_action('admin_notices', array($this, 'tfaShowHOTPOffSyncMessage'));
62 add_action('login_enqueue_scripts', array($this, 'login_enqueue_scripts'));
63 add_action('admin_menu', array($this, 'admin_menu'));
64
65 add_filter('authenticate', array($this, 'tfaVerifyCodeAndUser'), 99999999999, 3);
66 }
67
68 public function admin_notice_insufficient_php() {
69 $this->show_admin_warning('<strong>'.__('Higher PHP version required', 'updraftplus').'</strong><br> '.sprintf(__('The Two Factor Authentication plugin requires PHP version %s or higher - your current version is only %s.', SIMBA_TFA_TEXT_DOMAIN), $this->php_required, PHP_VERSION), 'error');
70 }
71
72 public function admin_notice_missing_mcrypt() {
73 $this->show_admin_warning('<strong>'.__('PHP Mcrypt module required', 'updraftplus').'</strong><br> '.__('The Two Factor Authentication plugin requires the PHP mcrypt module to be installed. Please ask your web hosting company to install it.', SIMBA_TFA_TEXT_DOMAIN), 'error');
74 }
75
76 private function show_admin_warning($message, $class = "updated") {
77 echo '<div class="updraftmessage '.$class.'">'."<p>$message</p></div>";
78 }
79
80 public function getTFA()
81 {
82 if (!class_exists('HOTP')) require_once(SIMBA_TFA_PLUGIN_DIR.'/hotp-php-master/hotp.php');
83 if (!class_exists('Base32')) require_once(SIMBA_TFA_PLUGIN_DIR.'/Base32/Base32.php');
84 if (!class_exists('Simba_TFA')) require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/class.TFA.php');
85
86 $tfa = new Simba_TFA(new Base32(), new HOTP());
87
88 return $tfa;
89 }
90
91 // "Shared" - i.e. could be called from either front-end or back-end
92 public function shared_ajax() {
93 if (empty($_POST['subaction']) || empty($_POST['nonce']) || !is_user_logged_in() || !wp_verify_nonce($_POST['nonce'], 'tfa_shared_nonce')) die('Security check.');
94
95 if ($_POST['subaction'] == 'refreshotp') {
96
97 global $current_user;
98
99 $tfa_priv_key_64 = get_user_meta($current_user->ID, 'tfa_priv_key_64', true);
100
101 if (!$tfa_priv_key_64) {
102 echo json_encode(array('code' => ''));
103 die;
104 }
105
106 echo json_encode(array('code' => $this->getTFA()->generateOTP($current_user->ID, $tfa_priv_key_64)));
107 exit;
108 }
109
110 }
111
112 public function tfaInitLogin() {
113
114 if (empty($_POST['user']) || empty($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'simba_tfa_loginform_nonce')) die('Security check.');
115
116 $tfa = $this->getTFA();
117 $res = $tfa->preAuth(array('log' => $_POST['user']));
118
119 echo json_encode(array('status' => $res));
120 exit;
121 }
122
123
124 // Here's where the login action happens
125 public function tfaVerifyCodeAndUser($user, $username, $password)
126 {
127
128 $tfa = $this->getTFA();
129
130 if (is_wp_error($user)) return $user;
131
132 $params = $_POST;
133 $params['log'] = $username;
134 $params['caller'] = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['REQUEST_URI'];
135
136 $code_ok = $tfa->authUserFromLogin($params);
137
138 if(!$code_ok)
139 return new WP_Error('authentication_failed', '<strong>'.__('Error:', SIMBA_TFA_TEXT_DOMAIN).'</strong> '.__('The one-time password (TFA code) you entered was incorrect.', SIMBA_TFA_TEXT_DOMAIN));
140
141 if($user)
142 return $user;
143
144 return wp_authenticate_username_password(null, $username, $password);
145 }
146
147 public function tfaRegisterTwoFactorAuthSettings()
148 {
149 global $wp_roles;
150 if (!isset($wp_roles))
151 $wp_roles = new WP_Roles();
152
153 foreach($wp_roles->role_names as $id => $name)
154 {
155 register_setting('tfa_user_roles_group', 'tfa_'.$id);
156 }
157
158 register_setting('simba_tfa_default_hmac_group', 'tfa_default_hmac');
159 register_setting('tfa_xmlrpc_status_group', 'tfa_xmlrpc_on');
160 }
161
162 public function tfaListEnableRadios($user_id, $long_label = false)
163 {
164 if(!$user_id)
165 return;
166
167 $setting = get_user_meta($user_id, 'tfa_enable_tfa', true);
168 $setting = !$setting ? false : $setting;
169
170 $tfa_enabled_label = ($long_label) ? __('Enable two-factor authentication', SIMBA_TFA_TEXT_DOMAIN) : __('Enabled', SIMBA_TFA_TEXT_DOMAIN);
171 $tfa_disabled_label = ($long_label) ? __('Disable two-factor authentication', SIMBA_TFA_TEXT_DOMAIN) : __('Disabled', SIMBA_TFA_TEXT_DOMAIN);
172
173 print '<input type="radio" id="tfa_enable_tfa_true" name="tfa_enable_tfa" value="true" '.($setting == true ? 'checked="checked"' :'').'> <label for="tfa_enable_tfa_true">'.apply_filters('simbatfa_radiolabel_enabled', $tfa_enabled_label, $long_label).'</label> <br>';
174 print '<input type="radio" id="tfa_enable_tfa_false" name="tfa_enable_tfa" value="false" '.($setting == false ? 'checked="checked"' :'').'> <label for="tfa_enable_tfa_false">'.apply_filters('simbatfa_radiolabel_disabled', $tfa_disabled_label, $long_label).'</label> <br>';
175 }
176
177
178 public function tfaListAlgorithmRadios($user_id)
179 {
180 if(!$user_id) return;
181
182 $types = array('totp' => __('TOTP (time based - most common algorithm; used by Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN), 'hotp' => __('HOTP (event based)', SIMBA_TFA_TEXT_DOMAIN));
183
184 $setting = get_user_meta($user_id, 'tfa_algorithm_type', true);
185 $setting = $setting === false || !$setting ? 'totp' : $setting;
186
187 foreach($types as $id => $name) {
188 print '<input type="radio" id="tfa_algorithm_type_'.esc_attr($id).'" name="tfa_algorithm_type" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> <label for="tfa_algorithm_type_'.esc_attr($id).'">'.$name."</label><br>\n";
189 }
190 }
191
192 public function tfaListUserRolesCheckboxes()
193 {
194 global $wp_roles;
195 if (!isset($wp_roles)) $wp_roles = new WP_Roles();
196
197 foreach($wp_roles->role_names as $id => $name)
198 {
199 $setting = get_option('tfa_'.$id);
200 $setting = $setting === false || $setting ? 1 : 0;
201
202 print '<input type="checkbox" id="tfa_'.$id.'" name="tfa_'.$id.'" value="1" '.($setting ? 'checked="checked"' :'').'> <label for="tfa_'.$id.'">'.htmlspecialchars($name)."</label><br>\n";
203 }
204
205 }
206
207 public function tfaListDefaultHMACRadios()
208 {
209 $tfa = $this->getTFA();
210 $setting = get_option('tfa_default_hmac');
211 $setting = $setting === false || !$setting ? $tfa->default_hmac : $setting;
212
213 $types = array('totp' => __('TOTP (time based - most common algorithm; used by Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN), 'hotp' => __('HOTP (event based)', SIMBA_TFA_TEXT_DOMAIN));
214
215 foreach($types as $id => $name)
216 print '<input type="radio" id="tfa_default_hmac_'.esc_attr($id).'" name="tfa_default_hmac" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> '.'<label for="tfa_default_hmac_'.esc_attr($id).'">'."$name</label><br>\n";
217 }
218
219
220 public function tfaListXMLRPCStatusRadios()
221 {
222 $tfa = $this->getTFA();
223 $setting = get_option('tfa_xmlrpc_on');
224 $setting = $setting === false || !$setting ? 0 : 1;
225
226 $types = array('0' => __('OFF', SIMBA_TFA_TEXT_DOMAIN), '1' => __('ON', SIMBA_TFA_TEXT_DOMAIN));
227
228 foreach($types as $id => $name)
229 print '<input type="radio" name="tfa_xmlrpc_on" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> - '.$name."<br>\n";
230 }
231
232
233 public function tfaShowAdminSettingsPage()
234 {
235 $tfa = $this->getTFA();
236 require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/admin_settings.php');
237 }
238
239 public function tfaShowUserSettingsPage()
240 {
241 $tfa = $this->getTFA();
242 include SIMBA_TFA_PLUGIN_DIR.'/includes/user_settings.php';
243 }
244
245
246 public function admin_menu()
247 {
248 $tfa = $this->getTFA();
249
250 global $current_user;
251 if(!$tfa->isActivatedForUser($current_user->ID)) return;
252
253 add_menu_page(__('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN), __('Two Factor Auth', SIMBA_TFA_TEXT_DOMAIN), 'read', 'two-factor-auth-user', array($this, 'tfaShowUserSettingsPage'), SIMBA_TFA_PLUGIN_URL.'/img/tfa_admin_icon_16x16.png', 72);
254 }
255
256 public function addTwoFactorAuthAdminMenu()
257 {
258 add_action( 'admin_init', array($this, 'tfaRegisterTwoFactorAuthSettings' ));
259 add_options_page('Two Factor Authentication', 'Two Factor Authentication', 'manage_options', 'two-factor-auth', array($this, 'tfaShowAdminSettingsPage'));
260 }
261
262 public function addPluginSettingsLink($links)
263 {
264
265 $link = '<a href="options-general.php?page=two-factor-auth">'.__('Plugin settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
266 array_unshift($links, $link);
267
268 $link2 = '<a href="admin.php?page=two-factor-auth-user">'.__('User settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
269 array_unshift($links, $link2);
270
271 return $links;
272 }
273
274 public function check_possible_reset() {
275 if(!empty($_GET['simbatfa_priv_key_reset']) && !empty($_REQUEST['nonce']) && wp_verify_nonce($_REQUEST['nonce'], 'simbatfa_reset_private_key'))
276 {
277 $this->reset_private_key_and_emergency_codes();
278 // if (empty($_REQUEST['noredirect'])) exit;
279 exit;
280 }
281
282 }
283
284 public function reset_private_key_and_emergency_codes() {
285 global $current_user;
286 delete_user_meta($current_user->ID, 'tfa_priv_key_64');
287 delete_user_meta($current_user->ID, 'simba_tfa_emergency_codes_64');
288 if (empty($_REQUEST['noredirect'])) {
289 wp_safe_redirect( admin_url('admin.php').'?page=two-factor-auth-user&settings-updated=1');
290 } else {
291 $url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . remove_query_arg(array('simbatfa_priv_key_reset', 'noredirect', 'nonce'));
292
293 wp_redirect($url);
294 }
295 }
296
297 public function reset_link($admin = true) {
298
299 $url_base = ($admin) ? admin_url('admin.php').'?page=two-factor-auth-user&settings-updated=1' : (( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST']);
300
301 $add_query_args = array(
302 'simbatfa_priv_key_reset' => 1,
303 );
304 if (!$admin) $add_query_args['noredirect'] = 1;
305
306 $url = $url_base.add_query_arg($add_query_args);
307
308 $url = wp_nonce_url($url, 'simbatfa_reset_private_key', 'nonce');
309
310 return '<a href="javascript:if(confirm(\''.__('Warning: if you reset this key you will have to update your apps with the new one. Are you sure you want this?', SIMBA_TFA_TEXT_DOMAIN).'\')){ window.location = \''.esc_js($url).'\'; }">'.__('Reset private key', SIMBA_TFA_TEXT_DOMAIN).'</a>';
311
312 }
313
314 public function footer() {
315 ?>
316 <script>
317 jQuery(document).ready(function($) {
318 $('.simbaotp_refresh').click(function(e) {
319 e.preventDefault();
320 $(".simba_current_otp").html('<em><?php echo esc_attr(__('Updating...', SIMBA_TFA_TEXT_DOMAIN));?></em>');
321 $.post('<?php echo esc_js(admin_url('admin-ajax.php'));?>', {
322 action: "simbatfa_shared_ajax",
323 subaction: "refreshotp",
324 nonce: "<?php echo esc_js(wp_create_nonce("tfa_shared_nonce"));?>"
325 }, function(response) {
326 try {
327 var resp = $.parseJSON(response);
328 $(".simba_current_otp").html(resp.code);
329 } catch(err) {
330 alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);
331 console.log(response);
332 console.log(err);
333 }
334 });
335 });
336 });
337 </script>
338 <?php
339 }
340
341 public function current_codes_box($admin = true) {
342
343 global $current_user;
344 $tfa = $this->getTFA();
345
346 static $added_footer;
347 if (empty($added_footer)) {
348 $added_footer = true;
349 wp_enqueue_script('jquery');
350 add_action( $admin ? 'admin_footer' : 'wp_footer' , array($this, 'footer'));
351 }
352
353 $url = preg_replace('/^https?:\/\//', '', site_url());
354
355 $tfa_priv_key_64 = get_user_meta($current_user->ID, 'tfa_priv_key_64', true);
356
357 if(!$tfa_priv_key_64) $tfa_priv_key_64 = $tfa->addPrivateKey($current_user->ID);
358
359 $tfa_priv_key = trim($tfa->getPrivateKeyPlain($tfa_priv_key_64, $current_user->ID));
360
361 $tfa_priv_key_32 = Base32::encode($tfa_priv_key);
362
363 $algorithm_type = $tfa->getUserAlgorithm($current_user->ID);
364
365
366 if ($admin) {
367 echo '<h2>'.__('Current codes', SIMBA_TFA_TEXT_DOMAIN).'</h2>';
368 } else {
369 // echo '<h2>'.__('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link().'</h2>';
370 }
371
372 ?>
373 <div class="postbox">
374
375 <?php if ($admin) { ?>
376 <h3 style="padding: 10px 6px 0px; margin:4px 0 0; cursor: default;">
377 <span style="cursor: default;"><?php echo __('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link(); ?> </span>
378 <div class="inside">
379 <p><strong style="font-size: 3em;"><span class="simba_current_otp"><?php print $tfa->generateOTP($current_user->ID, $tfa_priv_key_64); ?></span></strong></p>
380 </div>
381 </h3>
382 <?php } else {
383 ?>
384 <div class="inside">
385 <p class="simbatfa-frontend-current-otp" style="font-size: 1.5em; margin-top:6px;">
386 <strong>
387 <?php echo __('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link(); ?>
388 </strong> :
389
390 <span class="simba_current_otp"><?php print $tfa->generateOTP($current_user->ID, $tfa_priv_key_64); ?></span>
391
392 </p>
393 </div>
394
395 <?php } ?>
396
397 <?php if ($admin) { ?>
398 <h3 style="padding-left: 10px; cursor: default;">
399 <span style="cursor: default;"><?php _e('QR code', SIMBA_TFA_TEXT_DOMAIN); ?></span>
400 </h3>
401 <?php } else {
402 echo '<h2>'.__('QR code', SIMBA_TFA_TEXT_DOMAIN).'</h2>';
403 } ?>
404 <div class="inside">
405 <p>
406 <?php _e('Scan this code with Duo Mobile, Google Authenticator or any other app that supports 6 digit OTPs', SIMBA_TFA_TEXT_DOMAIN); ?>.
407
408 <?php _e('You are currently using', SIMBA_TFA_TEXT_DOMAIN); ?> <?php print strtoupper($algorithm_type).', '.($algorithm_type == 'totp' ? __('a time based', SIMBA_TFA_TEXT_DOMAIN) : __('an event based', SIMBA_TFA_TEXT_DOMAIN)); ?> <?php _e('algorithm', SIMBA_TFA_TEXT_DOMAIN); ?>.
409 </p>
410 <p title="<?php echo sprintf(__("Private key: %s (base 32: %s)", SIMBA_TFA_TEXT_DOMAIN), $tfa_priv_key, $tfa_priv_key_32);?>">
411 <?php echo $this->tfa_qr_code_url($algorithm_type, $url, $tfa_priv_key) ?>
412 </p>
413 </div>
414
415 <div class="inside">
416
417 <h3 class="normal" style="cursor: default"><?php _e('Private key - always to be kept secret', SIMBA_TFA_TEXT_DOMAIN); ?></h3>
418
419 <p>
420 <strong><?php echo __('Private key (base 32 - used by Google Authenticator and Authy):', SIMBA_TFA_TEXT_DOMAIN);?></strong>
421 <?php echo htmlspecialchars($tfa_priv_key_32); ?><br>
422
423 <strong><?php echo __('Private key:', SIMBA_TFA_TEXT_DOMAIN);?></strong>
424 <?php echo htmlspecialchars($tfa_priv_key); ?><br>
425
426 <?php echo $this->reset_link($admin); ?>
427 </p>
428 </div>
429
430 <?php
431 if ($admin || apply_filters('simba_tfa_emergency_codes_user_settings', false) !== false) {
432 ?>
433 <div class="inside">
434
435 <h3 class="normal" style="cursor: default"><?php _e('Emergency codes', SIMBA_TFA_TEXT_DOMAIN); ?></h3>
436
437 <p>
438 <?php
439 $default_text = __('One-time emergency codes are a feature of the Premium version of this plugin.', SIMBA_TFA_TEXT_DOMAIN);
440 echo apply_filters('simba_tfa_emergency_codes_user_settings', $default_text);
441 ?>
442 </p>
443
444 </div>
445
446 <?php } ?>
447
448 </div>
449 <?php
450 }
451
452 public function reset_current_otp_link($admin = true) {
453 return '<a href="#" class="simbaotp_refresh">'.__('(update)', SIMBA_TFA_TEXT_DOMAIN).'</a>';
454 }
455
456 public function advanced_settings_box($submit_button_callback = false) {
457 $tfa = $this->getTFA();
458
459 global $current_user;
460 $algorithm_type = $tfa->getUserAlgorithm($current_user->ID);
461
462 ?>
463 <h2><?php _e('Advanced settings', SIMBA_TFA_TEXT_DOMAIN); ?></h2>
464
465 <div id="tfa_advanced_box" class="tfa_settings_form" style="margin-top: 20px;">
466
467 <?php if (false === $submit_button_callback) { ?><form method="post" action="<?php print add_query_arg('settings-updated', 'true', $_SERVER['REQUEST_URI']); ?>"><?php } ?>
468
469 <?php _e('Choose which algorithm for One Time Passwords you want to use.', SIMBA_TFA_TEXT_DOMAIN); ?>
470 <p>
471 <?php
472 $this->tfaListAlgorithmRadios($current_user->ID);
473 if($algorithm_type == 'hotp')
474 {
475 $counter = $tfa->getUserCounter($current_user->ID);
476 print '<br>'.__('Your counter on the server is currently on', SIMBA_TFA_TEXT_DOMAIN).': '.$counter;
477 }
478 ?>
479
480 </p>
481 <?php if (false === $submit_button_callback) { submit_button(); echo '</form>'; } else { call_user_func($submit_button_callback); } ?>
482 </div>
483 <?php
484 }
485
486 public function login_enqueue_scripts()
487 {
488
489 if(isset($_GET['action']) && $_GET['action'] != 'logout' && $_GET['action'] != 'login') return;
490
491 // Prevent cacheing when in debug mode
492 $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $wp_version;
493
494 wp_enqueue_script( 'tfa-ajax-request', SIMBA_TFA_PLUGIN_URL . '/includes/tfa.js', array( 'jquery' ), $script_ver );
495 wp_localize_script( 'tfa-ajax-request', 'simba_tfasettings', array(
496 'ajaxurl' => admin_url('admin-ajax.php'),
497 'click_to_enter_otp' => __("Click to enter One Time Password", SIMBA_TFA_TEXT_DOMAIN),
498 'enter_username_first' => __('You have to enter a username first.', SIMBA_TFA_TEXT_DOMAIN),
499 'otp' => __("One Time Password (i.e. 2FA)", SIMBA_TFA_TEXT_DOMAIN),
500 'otp_login_help' => __('(check your OTP app to get this password)', SIMBA_TFA_TEXT_DOMAIN),
501 'nonce' => wp_create_nonce("simba_tfa_loginform_nonce")
502 ));
503 }
504
505 public function tfaShowHOTPOffSyncMessage()
506 {
507 global $current_user;
508 $is_off_sync = get_user_meta($current_user->ID, 'tfa_hotp_off_sync', true);
509 if(!$is_off_sync)
510 return;
511
512 ?>
513 <div class="error">
514 <h3><?php _e('Two Factor Authentication re-sync needed', SIMBA_TFA_TEXT_DOMAIN);?></h3>
515 <p>
516 You need to resync your mobile app for <strong>Two Factor Authentication</strong> since the OTP you last used is many steps ahead
517 of the server.
518 <br>
519 <?php _e('Please re-sync or you might not be able to log in if you generate more OTPs without logging in.', SIMBA_TFA_TEXT_DOMAIN);?>
520 <br><br>
521 <a href="admin.php?page=two-factor-auth-user&warning_button_clicked=1" class="button">Click here and re-scan the QR-Code</a>
522 </p>
523 </div>
524
525 <?php
526
527 }
528
529 // QR code image
530 public function tfa_qr_code_url($algorithm_type, $url, $tfa_priv_key){
531 global $current_user;
532 $tfa = $this->getTFA();
533
534 $ret = '<img src="https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://'.$algorithm_type.'/'.$url.':%2520'.$current_user->user_login.'%3Fsecret%3D'.Base32::encode($tfa_priv_key).'%26issuer='.$url.'%26counter='.$tfa->getUserCounter($current_user->ID).'">';
535 return $ret;
536 }
537
538 public function settings_intro_notices() {
539 ?>
540 <p class="simba_tfa_personal_settings_notice simba_tfa_intro_notice">
541 <?php echo __('These are your personal settings.', SIMBA_TFA_TEXT_DOMAIN).' '.__('Nothing you change here will have any effect on other users.', SIMBA_TFA_TEXT_DOMAIN); ?>
542 </p>
543 <p class="simba_tfa_verify_tfa_notice simba_tfa_intro_notice"><strong>
544 <?php _e('If you activate two-factor authentication, then verify with the One Time Password shown on this page before you log out.', SIMBA_TFA_TEXT_DOMAIN); ?></strong>
545 </p>
546 <?php
547 }
548
549 public function plugins_loaded()
550 {
551 load_plugin_textdomain(
552 SIMBA_TFA_TEXT_DOMAIN,
553 false,
554 dirname( plugin_basename( __FILE__ ) ) . '/languages/'
555 );
556
557 if ((!is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) && is_user_logged_in() && file_exists(SIMBA_TFA_PLUGIN_DIR.'/includes/tfa_frontend.php')) {
558 if (!class_exists('TFA_Frontend')) require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/tfa_frontend.php');
559 new TFA_Frontend($this);
560 } else {
561 add_shortcode('twofactor_user_settings', array($this, 'shortcode_when_not_logged_in'));
562 }
563
564 }
565
566 public function shortcode_when_not_logged_in() {
567 return '';
568 }
569
570 // WooCommerce login form
571 public function woocommerce_before_customer_login_form() {
572 wp_enqueue_script( 'tfa-wc-ajax-request', SIMBA_TFA_PLUGIN_URL.'/includes/wooextend.js', array('jquery'));
573 wp_localize_script( 'tfa-wc-ajax-request', 'simbatfa_wc_settings', array(
574 'ajaxurl' => admin_url('admin-ajax.php'),
575 'click_to_enter_otp' => __("Enter One Time Password (if you have one)", SIMBA_TFA_TEXT_DOMAIN),
576 'enter_username_first' => __('You have to enter a username first.', SIMBA_TFA_TEXT_DOMAIN),
577 'otp' => __("One Time Password", SIMBA_TFA_TEXT_DOMAIN),
578 'nonce' => wp_create_nonce("simba_tfa_loginform_nonce")
579 ));
580 }
581
582 }
583
584 $simba_two_factor_authentication = new Simba_Two_Factor_Authentication();