PluginProbe
Google Authenticator / 0.48
Google Authenticator v0.48
trunk 0.20 0.30 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.50 0.51 0.52 0.53 0.54 0.55 0.56
google-authenticator / google-authenticator.php

google-authenticator.php in Google Authenticator 0.48, at google-authenticator.php

550 lines 20.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Google Authenticator
4 Plugin URI: http://henrik.schack.dk/google-authenticator-for-wordpress
5 Description: Two-Factor Authentication for WordPress using the Android/iPhone/Blackberry app as One Time Password generator.
6 Author: Henrik Schack
7 Version: 0.48
8 Author URI: http://henrik.schack.dk/
9 Compatibility: WordPress 4.5
10 Text Domain: google-authenticator
11 Domain Path: /lang
12
13 ----------------------------------------------------------------------------
14
15 Thanks to Bryan Ruiz for his Base32 encode/decode class, found at php.net.
16 Thanks to Tobias B�thge for his major code rewrite and German translation.
17 Thanks to Pascal de Bruijn for his relaxed mode idea.
18 Thanks to Daniel Werl for his usability tips.
19 Thanks to Dion Hulse for his bugfixes.
20 Thanks to Aldo Latino for his Italian translation.
21 Thanks to Kaijia Feng for his Simplified Chinese translation.
22 Thanks to Ian Dunn for fixing some depricated function calls.
23 Thanks to Kimmo Suominen for fixing the iPhone description issue.
24 Thanks to Alex Concha for some security tips.
25 Thanks to S�bastien Prunier for his Spanish and French translations.
26
27 ----------------------------------------------------------------------------
28
29 Copyright 2013 Henrik Schack (email : henrik@schack.dk)
30
31 This program is free software; you can redistribute it and/or modify
32 it under the terms of the GNU General Public License as published by
33 the Free Software Foundation; either version 2 of the License, or
34 (at your option) any later version.
35
36 This program is distributed in the hope that it will be useful,
37 but WITHOUT ANY WARRANTY; without even the implied warranty of
38 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 GNU General Public License for more details.
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
44 */
45
46 class GoogleAuthenticator {
47
48 static $instance; // to store a reference to the plugin, allows other plugins to remove actions
49
50 /**
51 * Constructor, entry point of the plugin
52 */
53 function __construct() {
54 self::$instance = $this;
55 add_action( 'init', array( $this, 'init' ) );
56 }
57
58 /**
59 * Initialization, Hooks, and localization
60 */
61 function init() {
62 require_once( 'base32.php' );
63
64 add_action( 'login_form', array( $this, 'loginform' ) );
65 add_action( 'login_footer', array( $this, 'loginfooter' ) );
66 add_filter( 'authenticate', array( $this, 'check_otp' ), 50, 3 );
67
68 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
69 add_action( 'wp_ajax_GoogleAuthenticator_action', array( $this, 'ajax_callback' ) );
70 }
71
72 add_action( 'personal_options_update', array( $this, 'personal_options_update' ) );
73 add_action( 'profile_personal_options', array( $this, 'profile_personal_options' ) );
74 add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) );
75 add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) );
76
77 add_action('admin_enqueue_scripts', array($this, 'add_qrcode_script'));
78
79 load_plugin_textdomain( 'google-authenticator', false, basename( dirname( __FILE__ ) ) . '/lang' );
80 }
81
82
83 /**
84 * Check the verification code entered by the user.
85 */
86 function verify( $secretkey, $thistry, $relaxedmode, $lasttimeslot ) {
87
88 // Did the user enter 6 digits ?
89 if ( strlen( $thistry ) != 6) {
90 return false;
91 } else {
92 $thistry = intval ( $thistry );
93 }
94
95 // If user is running in relaxed mode, we allow more time drifting
96 // �4 min, as opposed to � 30 seconds in normal mode.
97 if ( $relaxedmode == 'enabled' ) {
98 $firstcount = -8;
99 $lastcount = 8;
100 } else {
101 $firstcount = -1;
102 $lastcount = 1;
103 }
104
105 $tm = floor( time() / 30 );
106
107 $secretkey=Base32::decode($secretkey);
108 // Keys from 30 seconds before and after are valid aswell.
109 for ($i=$firstcount; $i<=$lastcount; $i++) {
110 // Pack time into binary string
111 $time=chr(0).chr(0).chr(0).chr(0).pack('N*',$tm+$i);
112 // Hash it with users secret key
113 $hm = hash_hmac( 'SHA1', $time, $secretkey, true );
114 // Use last nipple of result as index/offset
115 $offset = ord(substr($hm,-1)) & 0x0F;
116 // grab 4 bytes of the result
117 $hashpart=substr($hm,$offset,4);
118 // Unpak binary value
119 $value=unpack("N",$hashpart);
120 $value=$value[1];
121 // Only 32 bits
122 $value = $value & 0x7FFFFFFF;
123 $value = $value % 1000000;
124 if ( $value === $thistry ) {
125 // Check for replay (Man-in-the-middle) attack.
126 // Since this is not Star Trek, time can only move forward,
127 // meaning current login attempt has to be in the future compared to
128 // last successful login.
129 if ( $lasttimeslot >= ($tm+$i) ) {
130 error_log("Google Authenticator plugin: Man-in-the-middle attack detected (Could also be 2 legit login attempts within the same 30 second period)");
131 return false;
132 }
133 // Return timeslot in which login happened.
134 return $tm+$i;
135 }
136 }
137 return false;
138 }
139
140 /**
141 * Create a new random secret for the Google Authenticator app.
142 * 16 characters, randomly chosen from the allowed Base32 characters
143 * equals 10 bytes = 80 bits, as 256^10 = 32^16 = 2^80
144 */
145 function create_secret() {
146 $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; // allowed characters in Base32
147 $secret = '';
148 for ( $i = 0; $i < 16; $i++ ) {
149 $secret .= substr( $chars, wp_rand( 0, strlen( $chars ) - 1 ), 1 );
150 }
151 return $secret;
152 }
153
154 /**
155 * Add the script to generate QR codes.
156 */
157 function add_qrcode_script() {
158 wp_enqueue_script('jquery');
159 wp_register_script('qrcode_script', plugins_url('jquery.qrcode.min.js', __FILE__),array("jquery"));
160 wp_enqueue_script('qrcode_script');
161 }
162
163 /**
164 * Add verification code field to login form.
165 */
166 function loginform() {
167 echo "\t<p>\n";
168 echo "\t\t<label title=\"".__('If you don\'t have Google Authenticator enabled for your WordPress account, leave this field empty.','google-authenticator')."\">".__('Google Authenticator code','google-authenticator')."<span id=\"google-auth-info\"></span><br />\n";
169 echo "\t\t<input type=\"text\" name=\"googleotp\" id=\"user_email\" class=\"input\" value=\"\" size=\"20\" style=\"ime-mode: inactive;\" /></label>\n";
170 echo "\t</p>\n";
171 }
172
173 /**
174 * Disable autocomplete on Google Authenticator code input field.
175 */
176 function loginfooter() {
177 echo "\n<script type=\"text/javascript\">\n";
178 echo "\ttry{\n";
179 echo "\t\tdocument.getElementById('user_email').setAttribute('autocomplete','off');\n";
180 echo "\t} catch(e){}\n";
181 echo "</script>\n";
182 }
183
184 /**
185 * Login form handling.
186 * Check Google Authenticator verification code, if user has been setup to do so.
187 * @param wordpressuser
188 * @return user/loginstatus
189 */
190 function check_otp( $user, $username = '', $password = '' ) {
191 // Store result of loginprocess, so far.
192 $userstate = $user;
193
194 // Get information on user, we need this in case an app password has been enabled,
195 // since the $user var only contain an error at this point in the login flow.
196 if ( get_user_by( 'email', $username ) === false ) {
197 $user = get_user_by( 'login', $username );
198 } else {
199 $user = get_user_by( 'email', $username );
200 }
201
202 // Does the user have the Google Authenticator enabled ?
203 if ( isset( $user->ID ) && trim(get_user_option( 'googleauthenticator_enabled', $user->ID ) ) == 'enabled' ) {
204
205 // Get the users secret
206 $GA_secret = trim( get_user_option( 'googleauthenticator_secret', $user->ID ) );
207
208 // Figure out if user is using relaxed mode ?
209 $GA_relaxedmode = trim( get_user_option( 'googleauthenticator_relaxedmode', $user->ID ) );
210
211 // Get the verification code entered by the user trying to login
212 if ( !empty( $_POST['googleotp'] )) { // Prevent PHP notices when using app password login
213 $otp = trim( $_POST[ 'googleotp' ] );
214 } else {
215 $otp = '';
216 }
217 // When was the last successful login performed ?
218 $lasttimeslot = trim( get_user_option( 'googleauthenticator_lasttimeslot', $user->ID ) );
219 // Valid code ?
220 if ( $timeslot = $this->verify( $GA_secret, $otp, $GA_relaxedmode, $lasttimeslot ) ) {
221 // Store the timeslot in which login was successful.
222 update_user_option( $user->ID, 'googleauthenticator_lasttimeslot', $timeslot, true );
223 return $userstate;
224 } else {
225 // No, lets see if an app password is enabled, and this is an XMLRPC / APP login ?
226 if ( trim( get_user_option( 'googleauthenticator_pwdenabled', $user->ID ) ) == 'enabled' && ( defined('XMLRPC_REQUEST') || defined('APP_REQUEST') ) ) {
227 $GA_passwords = json_decode( get_user_option( 'googleauthenticator_passwords', $user->ID ) );
228 $passwordhash = trim($GA_passwords->{'password'} );
229 $usersha1 = sha1( strtoupper( str_replace( ' ', '', $password ) ) );
230 if ( $passwordhash == $usersha1 ) { // ToDo: Remove after some time when users have migrated to new format
231 return new WP_User( $user->ID );
232 // Try the new version based on thee wp_hash_password function
233 } elseif (wp_check_password( strtoupper( str_replace( ' ', '', $password ) ), $passwordhash)) {
234 return new WP_User( $user->ID );
235 } else {
236 // Wrong XMLRPC/APP password !
237 return new WP_Error( 'invalid_google_authenticator_password', __( '<strong>ERROR</strong>: The Google Authenticator password is incorrect.', 'google-authenticator' ) );
238 }
239 } else {
240 return new WP_Error( 'invalid_google_authenticator_token', __( '<strong>ERROR</strong>: The Google Authenticator code is incorrect or has expired.', 'google-authenticator' ) );
241 }
242 }
243 }
244 // Google Authenticator isn't enabled for this account,
245 // just resume normal authentication.
246 return $userstate;
247 }
248
249
250 /**
251 * Extend personal profile page with Google Authenticator settings.
252 */
253 function profile_personal_options() {
254 global $user_id, $is_profile_page;
255
256 // If editing of Google Authenticator settings has been disabled, just return
257 $GA_hidefromuser = trim( get_user_option( 'googleauthenticator_hidefromuser', $user_id ) );
258 if ( $GA_hidefromuser == 'enabled') return;
259
260 $GA_secret = trim( get_user_option( 'googleauthenticator_secret', $user_id ) );
261 $GA_enabled = trim( get_user_option( 'googleauthenticator_enabled', $user_id ) );
262 $GA_relaxedmode = trim( get_user_option( 'googleauthenticator_relaxedmode', $user_id ) );
263 $GA_description = trim( get_user_option( 'googleauthenticator_description', $user_id ) );
264 $GA_pwdenabled = trim( get_user_option( 'googleauthenticator_pwdenabled', $user_id ) );
265 $GA_password = trim( get_user_option( 'googleauthenticator_passwords', $user_id ) );
266
267 // We dont store the generated app password in cleartext so there is no point in trying
268 // to show the user anything except from the fact that a password exists.
269 if ( $GA_password != '' ) {
270 $GA_password = "XXXX XXXX XXXX XXXX";
271 }
272
273 // In case the user has no secret ready (new install), we create one.
274 if ( '' == $GA_secret ) {
275 $GA_secret = $this->create_secret();
276 }
277
278 // Use "WordPress Blog" as default description
279 if ( '' == $GA_description ) {
280 $GA_description = __( 'WordPressBlog', 'google-authenticator' );
281 }
282
283 echo "<h3>".__( 'Google Authenticator Settings', 'google-authenticator' )."</h3>\n";
284
285 echo "<table class=\"form-table\">\n";
286 echo "<tbody>\n";
287 echo "<tr>\n";
288 echo "<th scope=\"row\">".__( 'Active', 'google-authenticator' )."</th>\n";
289 echo "<td>\n";
290 echo "<input name=\"GA_enabled\" id=\"GA_enabled\" class=\"tog\" type=\"checkbox\"" . checked( $GA_enabled, 'enabled', false ) . "/>\n";
291 echo "</td>\n";
292 echo "</tr>\n";
293
294 if ( $is_profile_page || IS_PROFILE_PAGE ) {
295 echo "<tr>\n";
296 echo "<th scope=\"row\">".__( 'Relaxed mode', 'google-authenticator' )."</th>\n";
297 echo "<td>\n";
298 echo "<input name=\"GA_relaxedmode\" id=\"GA_relaxedmode\" class=\"tog\" type=\"checkbox\"" . checked( $GA_relaxedmode, 'enabled', false ) . "/><span class=\"description\">".__(' Relaxed mode allows for more time drifting on your phone clock (&#177;4 min).','google-authenticator')."</span>\n";
299 echo "</td>\n";
300 echo "</tr>\n";
301
302 echo "<tr>\n";
303 echo "<th><label for=\"GA_description\">".__('Description','google-authenticator')."</label></th>\n";
304 echo "<td><input name=\"GA_description\" id=\"GA_description\" value=\"{$GA_description}\" type=\"text\" size=\"25\" /><span class=\"description\">".__(' Description that you\'ll see in the Google Authenticator app on your phone.','google-authenticator')."</span><br /></td>\n";
305 echo "</tr>\n";
306
307 echo "<tr>\n";
308 echo "<th><label for=\"GA_secret\">".__('Secret','google-authenticator')."</label></th>\n";
309 echo "<td>\n";
310 echo "<input name=\"GA_secret\" id=\"GA_secret\" value=\"{$GA_secret}\" readonly=\"readonly\" type=\"text\" size=\"25\" />";
311 echo "<input name=\"GA_newsecret\" id=\"GA_newsecret\" value=\"".__("Create new secret",'google-authenticator')."\" type=\"button\" class=\"button\" />";
312 echo "<input name=\"show_qr\" id=\"show_qr\" value=\"".__("Show/Hide QR code",'google-authenticator')."\" type=\"button\" class=\"button\" onclick=\"ShowOrHideQRCode();\" />";
313 echo "</td>\n";
314 echo "</tr>\n";
315
316 echo "<tr>\n";
317 echo "<th></th>\n";
318 echo "<td><div id=\"GA_QR_INFO\" style=\"display: none\" >";
319 echo "<div id=\"GA_QRCODE\"/></div>";
320
321 echo '<span class="description"><br/> ' . __( 'Scan this with the Google Authenticator app.', 'google-authenticator' ) . '</span>';
322 echo "</div></td>\n";
323 echo "</tr>\n";
324
325 echo "<tr>\n";
326 echo "<th scope=\"row\">".__( 'Enable App password', 'google-authenticator' )."</th>\n";
327 echo "<td>\n";
328 echo "<input name=\"GA_pwdenabled\" id=\"GA_pwdenabled\" class=\"tog\" type=\"checkbox\"" . checked( $GA_pwdenabled, 'enabled', false ) . "/><span class=\"description\">".__(' Enabling an App password will decrease your overall login security.','google-authenticator')."</span>\n";
329 echo "</td>\n";
330 echo "</tr>\n";
331
332 echo "<tr>\n";
333 echo "<th></th>\n";
334 echo "<td>\n";
335 echo "<input name=\"GA_password\" id=\"GA_password\" readonly=\"readonly\" value=\"".$GA_password."\" type=\"text\" size=\"25\" />";
336 echo "<input name=\"GA_createpassword\" id=\"GA_createpassword\" value=\"".__("Create new password",'google-authenticator')."\" type=\"button\" class=\"button\" />";
337 echo "<span class=\"description\" id=\"GA_passworddesc\"> ".__(' Password is not stored in cleartext, this is your only chance to see it.','google-authenticator')."</span>\n";
338 echo "</td>\n";
339 echo "</tr>\n";
340 }
341
342 echo "</tbody></table>\n";
343 echo "<script type=\"text/javascript\">\n";
344 echo "var GAnonce='".wp_create_nonce('GoogleAuthenticatoraction')."';\n";
345
346 echo <<<ENDOFJS
347 //Create new secret and display it
348 jQuery('#GA_newsecret').bind('click', function() {
349 // Remove existing QRCode
350 jQuery('#GA_QRCODE').html("");
351 var data=new Object();
352 data['action'] = 'GoogleAuthenticator_action';
353 data['nonce'] = GAnonce;
354 jQuery.post(ajaxurl, data, function(response) {
355 jQuery('#GA_secret').val(response['new-secret']);
356 var qrcode="otpauth://totp/WordPress:"+escape(jQuery('#GA_description').val())+"?secret="+jQuery('#GA_secret').val()+"&issuer=WordPress";
357 jQuery('#GA_QRCODE').qrcode(qrcode);
358 jQuery('#GA_QR_INFO').show('slow');
359 });
360 });
361
362 // If the user starts modifying the description, hide the qrcode
363 jQuery('#GA_description').bind('focus blur change keyup', function() {
364 // Only remove QR Code if it's visible
365 if (jQuery('#GA_QR_INFO').is(':visible')) {
366 jQuery('#GA_QR_INFO').hide('slow');
367 jQuery('#GA_QRCODE').html("");
368 }
369 });
370
371 // Create new app password
372 jQuery('#GA_createpassword').bind('click',function() {
373 var data=new Object();
374 data['action'] = 'GoogleAuthenticator_action';
375 data['nonce'] = GAnonce;
376 data['save'] = 1;
377 jQuery.post(ajaxurl, data, function(response) {
378 jQuery('#GA_password').val(response['new-secret'].match(new RegExp(".{0,4}","g")).join(' '));
379 jQuery('#GA_passworddesc').show();
380 });
381 });
382
383 jQuery('#GA_enabled').bind('change',function() {
384 GoogleAuthenticator_apppasswordcontrol();
385 });
386
387 jQuery(document).ready(function() {
388 jQuery('#GA_passworddesc').hide();
389 GoogleAuthenticator_apppasswordcontrol();
390 });
391
392 function GoogleAuthenticator_apppasswordcontrol() {
393 if (jQuery('#GA_enabled').is(':checked')) {
394 jQuery('#GA_pwdenabled').removeAttr('disabled');
395 jQuery('#GA_createpassword').removeAttr('disabled');
396 } else {
397 jQuery('#GA_pwdenabled').removeAttr('checked')
398 jQuery('#GA_pwdenabled').attr('disabled', true);
399 jQuery('#GA_createpassword').attr('disabled', true);
400 }
401 }
402
403 function ShowOrHideQRCode() {
404 if (jQuery('#GA_QR_INFO').is(':hidden')) {
405 var qrcode="otpauth://totp/WordPress:"+escape(jQuery('#GA_description').val())+"?secret="+jQuery('#GA_secret').val()+"&issuer=WordPress";
406 jQuery('#GA_QRCODE').qrcode(qrcode);
407 jQuery('#GA_QR_INFO').show('slow');
408 } else {
409 jQuery('#GA_QR_INFO').hide('slow');
410 jQuery('#GA_QRCODE').html("");
411 }
412 }
413 </script>
414 ENDOFJS;
415 }
416
417 /**
418 * Form handling of Google Authenticator options added to personal profile page (user editing his own profile)
419 */
420 function personal_options_update() {
421 global $user_id;
422
423 // If editing of Google Authenticator settings has been disabled, just return
424 $GA_hidefromuser = trim( get_user_option( 'googleauthenticator_hidefromuser', $user_id ) );
425 if ( $GA_hidefromuser == 'enabled') return;
426
427
428 $GA_enabled = ! empty( $_POST['GA_enabled'] );
429 $GA_description = trim( sanitize_text_field($_POST['GA_description'] ) );
430 $GA_relaxedmode = ! empty( $_POST['GA_relaxedmode'] );
431 $GA_secret = trim( $_POST['GA_secret'] );
432 $GA_pwdenabled = ! empty( $_POST['GA_pwdenabled'] );
433 $GA_password = str_replace(' ', '', trim( $_POST['GA_password'] ) );
434
435 if ( ! $GA_enabled ) {
436 $GA_enabled = 'disabled';
437 } else {
438 $GA_enabled = 'enabled';
439 }
440
441 if ( ! $GA_relaxedmode ) {
442 $GA_relaxedmode = 'disabled';
443 } else {
444 $GA_relaxedmode = 'enabled';
445 }
446
447
448 if ( ! $GA_pwdenabled ) {
449 $GA_pwdenabled = 'disabled';
450 } else {
451 $GA_pwdenabled = 'enabled';
452 }
453
454 // Only store password if a new one has been generated.
455 if (strtoupper($GA_password) != 'XXXXXXXXXXXXXXXX' ) {
456 // Store the password in a format that can be expanded easily later on if needed.
457 $GA_password = array( 'appname' => 'Default', 'password' => wp_hash_password( $GA_password ) );
458 update_user_option( $user_id, 'googleauthenticator_passwords', json_encode( $GA_password ), true );
459 }
460
461 update_user_option( $user_id, 'googleauthenticator_enabled', $GA_enabled, true );
462 update_user_option( $user_id, 'googleauthenticator_description', $GA_description, true );
463 update_user_option( $user_id, 'googleauthenticator_relaxedmode', $GA_relaxedmode, true );
464 update_user_option( $user_id, 'googleauthenticator_secret', $GA_secret, true );
465 update_user_option( $user_id, 'googleauthenticator_pwdenabled', $GA_pwdenabled, true );
466
467 }
468
469 /**
470 * Extend profile page with ability to enable/disable Google Authenticator authentication requirement.
471 * Used by an administrator when editing other users.
472 */
473 function edit_user_profile() {
474 global $user_id;
475 $GA_enabled = trim( get_user_option( 'googleauthenticator_enabled', $user_id ) );
476 $GA_hidefromuser = trim( get_user_option( 'googleauthenticator_hidefromuser', $user_id ) );
477 echo "<h3>".__('Google Authenticator Settings','google-authenticator')."</h3>\n";
478 echo "<table class=\"form-table\">\n";
479 echo "<tbody>\n";
480
481 echo "<tr>\n";
482 echo "<th scope=\"row\">".__('Hide settings from user','google-authenticator')."</th>\n";
483 echo "<td>\n";
484 echo "<div><input name=\"GA_hidefromuser\" id=\"GA_hidefromuser\" class=\"tog\" type=\"checkbox\"" . checked( $GA_hidefromuser, 'enabled', false ) . "/>\n";
485 echo "</td>\n";
486 echo "</tr>\n";
487
488 echo "<tr>\n";
489 echo "<th scope=\"row\">".__('Active','google-authenticator')."</th>\n";
490 echo "<td>\n";
491 echo "<div><input name=\"GA_enabled\" id=\"GA_enabled\" class=\"tog\" type=\"checkbox\"" . checked( $GA_enabled, 'enabled', false ) . "/>\n";
492 echo "</td>\n";
493 echo "</tr>\n";
494
495 echo "</tbody>\n";
496 echo "</table>\n";
497 }
498
499 /**
500 * Form handling of Google Authenticator options on edit profile page (admin user editing other user)
501 */
502 function edit_user_profile_update() {
503 global $user_id;
504
505 $GA_enabled = ! empty( $_POST['GA_enabled'] );
506 $GA_hidefromuser = ! empty( $_POST['GA_hidefromuser'] );
507
508 if ( ! $GA_enabled ) {
509 $GA_enabled = 'disabled';
510 } else {
511 $GA_enabled = 'enabled';
512 }
513
514 if ( ! $GA_hidefromuser ) {
515 $GA_hidefromuser = 'disabled';
516 } else {
517 $GA_hidefromuser = 'enabled';
518 }
519
520 update_user_option( $user_id, 'googleauthenticator_enabled', $GA_enabled, true );
521 update_user_option( $user_id, 'googleauthenticator_hidefromuser', $GA_hidefromuser, true );
522
523 }
524
525
526 /**
527 * AJAX callback function used to generate new secret
528 */
529 function ajax_callback() {
530 global $user_id;
531
532 // Some AJAX security.
533 check_ajax_referer( 'GoogleAuthenticatoraction', 'nonce' );
534
535 // Create new secret.
536 $secret = $this->create_secret();
537
538 $result = array( 'new-secret' => $secret );
539 header( 'Content-Type: application/json' );
540 echo json_encode( $result );
541
542 // die() is required to return a proper result
543 die();
544 }
545
546 } // end class
547
548 $google_authenticator = new GoogleAuthenticator;
549 ?>
550