Google Authenticator - Version 0.30

Version Description

  • Code cleanup
  • Changed generation of secret key, to no longer have requirement of SHA256 on the server
  • German translation
Download this release

Release Info

Developer Henrik.Schack
Plugin Icon wp plugin Google Authenticator
Version 0.30
Comparing to
See all releases

Code changes from version 0.20 to 0.30

google-authenticator.php CHANGED
@@ -2,17 +2,18 @@
2
  /*
3
  Plugin Name: Google Authenticator
4
  Plugin URI: http://henrik.schack.dk/google-authenticator-for-wordpress
5
- Description: Multi-Factor Authentication for Wordpress using the Android/Iphone/Blackberry app as One Time Password generator.
6
  Author: Henrik Schack
7
- Version: 0.20
8
  Author URI: http://henrik.schack.dk/
9
- Compatibility : WordPress 3.1.2
10
- Text Domain: google-auth
11
  Domain Path: /lang
12
 
13
  ----------------------------------------------------------------------------
14
 
15
- Thanks to Bryan Ruiz for his Base32 encode/decode class, found at php.net
 
16
 
17
  ----------------------------------------------------------------------------
18
 
@@ -33,15 +34,44 @@ Domain Path: /lang
33
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34
  */
35
 
36
- require_once('base32.php');
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  /**
40
  * Check the verification code entered by the user.
41
  */
42
- function GoogleAuthenticate($secretkey,$thistry) {
43
 
44
- $tm=intval(time()/30);
45
 
46
  $secretkey=Base32::decode($secretkey);
47
  // Keys from 30 seconds before and after are valid aswell.
@@ -49,7 +79,7 @@ function GoogleAuthenticate($secretkey,$thistry) {
49
  // Pack time into binary string
50
  $time=chr(0).chr(0).chr(0).chr(0).pack('N*',$tm+$i);
51
  // Hash it with users secret key
52
- $hm=hash_hmac ('SHA1' ,$time, $secretkey,true);
53
  // Use last nipple of result as index/offset
54
  $offset = ord(substr($hm,-1)) & 0x0F;
55
  // grab 4 bytes of the result
@@ -59,36 +89,37 @@ function GoogleAuthenticate($secretkey,$thistry) {
59
  $value=$value[1];
60
  // Only 32 bits
61
  $value = $value & 0x7FFFFFFF;
62
- $value = bcmod($value,1000000) ;
63
- if ($value == $thistry) {
64
  return true;
65
- }
66
  }
67
  return false;
68
  }
69
 
70
  /**
71
- * Create a new secret for the Google Authenticator app.
72
- * Hash the current time, with the hash of the users password
73
- * then grap 10 bytes of the result using lower nipple as offset
74
- * into the datastring.
75
  */
76
- function GoogleAuthenticator_create_secret($inputvalue) {
77
- $rawsecret = hash_hmac('SHA256',microtime(),$inputvalue,true);
78
- $offset = ord(substr($rawsecret,-1)) & 0x0F;
79
- $secret = substr($rawsecret,$offset,10);
80
- return Base32::encode($secret);
 
 
81
  }
82
 
83
 
84
  /**
85
  * Add verification code field to login form.
86
  */
87
- function GoogleAuthenticator_loginform() {
88
- echo "\t<p>\n";
89
- echo "\t\t<label><a href=\"http://code.google.com/p/google-authenticator/\" target=\"_blank\" title=\"".__('If You don\'t have Google Authenticator enabled for Your Wordpress account, leave this field empty.','google-auth')."\">".__('Google Authenticator code','google-auth')."</a><span id=\"google-auth-info\"></span><br />\n";
90
- echo "\t\t<input type=\"password\" name=\"otp\" id=\"user_email\" class=\"input\" value=\"\" size=\"20\" tabindex=\"25\" /></label>\n";
91
- echo "\t</p>\n";
92
  }
93
 
94
 
@@ -98,7 +129,7 @@ function GoogleAuthenticator_loginform() {
98
  * @param wordpressuser
99
  * @return user/loginstatus
100
  */
101
- function GoogleAuthenticator_check_otp( $user ) {
102
 
103
  // Does the user have the Google Authenticator enabled ?
104
  if ( trim(get_user_option('googleauthenticator_enabled',$user->ID)) == 'enabled' ) {
@@ -110,9 +141,8 @@ function GoogleAuthenticator_check_otp( $user ) {
110
  $otp = intval( trim( $_POST[ 'otp' ] ) );
111
 
112
  // Valid code ?
113
- if (! GoogleAuthenticate( $GA_secret, $otp ) ) {
114
- return false;
115
- }
116
  }
117
  return $user;
118
  }
@@ -121,7 +151,7 @@ function GoogleAuthenticator_check_otp( $user ) {
121
  /**
122
  * Extend personal profile page with Google Authenticator settings.
123
  */
124
- function GoogleAuthenticator_profile_personal_options() {
125
  global $user_id, $is_profile_page;
126
 
127
  $GA_secret =trim( get_user_option( 'googleauthenticator_secret', $user_id ) );
@@ -129,57 +159,48 @@ function GoogleAuthenticator_profile_personal_options() {
129
  $GA_description =trim( get_user_option( 'googleauthenticator_description', $user_id ) );
130
 
131
  // In case the user has no secret ready (new install), we create one.
132
- if ($GA_secret == "") {
133
- $GA_secret=GoogleAuthenticator_create_secret( get_user_option( 'user_pass', $user_id ) );
134
- }
135
 
136
- // Use "Wordpress blog" as default description
137
- if ($GA_description == "") {
138
- $GA_description=__("Wordpress blog",'google-auth');
139
- }
140
 
141
- echo "<h3>".__( 'Google Authenticator settings', 'google-auth' )."</h3>\n";
142
 
143
  echo "<table class=\"form-table\">\n";
144
  echo "<tbody>\n";
145
  echo "<tr>\n";
146
- echo "<th scope=\"row\">".__( 'Active', 'google-auth' )."</th>\n";
147
  echo "<td>\n";
148
-
149
- echo "<div><input name=\"GA_enabled\" id=\"GA_enabled\" class=\"tog\" type=\"checkbox\"";
150
- if ( $GA_enabled == 'enabled' ) {
151
- echo ' checked="checked"';
152
- }
153
- echo "/>";
154
- echo "</div>\n";
155
-
156
  echo "</td>\n";
157
  echo "</tr>\n";
158
 
159
  // Create URL for the Google charts QR code generator.
160
- $chl=urlencode("otpauth://totp/".$GA_description."?secret=".$GA_secret);
161
- $qrcodeurl="http://chart.apis.google.com/chart?cht=qr&amp;chs=300x300&amp;chld=H|0&amp;chl=".$chl;
162
 
163
  if ( $is_profile_page || IS_PROFILE_PAGE ) {
164
  echo "<tr>\n";
165
- echo "<th><label for=\"GA_description\">".__('Description','google-auth')."</label></th>\n";
166
- echo "<td><input name=\"GA_description\" id=\"GA_description\" value=\"".$GA_description."\" type=\"text\" /><span class=\"description\">".__(' Description you\'ll see on your phone.','google-auth')."</span><br /></td>\n";
167
  echo "</tr>\n";
168
 
169
  echo "<tr>\n";
170
- echo "<th><label for=\"GA_secret\">".__('Secret','google-auth')."</label></th>\n";
171
  echo "<td>\n";
172
- echo "<input name=\"GA_secret\" id=\"GA_secret\" value=\"".$GA_secret."\" readonly=\"true\" type=\"text\" />";
173
- echo "<input name=\"GA_newsecret\" id=\"GA_newsecret\" value=\"".__("Create new secret",'google-auth')."\" type=\"button\" class=\"button\" />";
174
- echo "<input name=\"show_qr\" id=\"show_qr\" value=\"".__("Show/Hide QR code",'google-auth')."\" type=\"button\" class=\"button\" onclick=\"jQuery('#GA_QR_INFO').toggle('slow');\" />";
175
  echo "</td>\n";
176
  echo "</tr>\n";
177
 
178
  echo "<tr>\n";
179
  echo "<th></th>\n";
180
  echo "<td><div id=\"GA_QR_INFO\" style=\"display: none\" >";
181
- echo "<img id=\"GA_QRCODE\" src=\"".$qrcodeurl."\" alt=\"QR Code\"/>";
182
- echo "<span class=\"description\">".__('<br/> Scan this with the Google Authenticator app.','google-auth')."</span>";
183
  echo "</div></td>\n";
184
  echo "</tr>\n";
185
 
@@ -188,7 +209,6 @@ function GoogleAuthenticator_profile_personal_options() {
188
 
189
  echo "</tbody></table>\n";
190
  echo "<script type=\"text/javascript\">\n";
191
- echo "var ajaxurl='".admin_url( 'admin-ajax.php' )."'\n";
192
  echo "var GAnonce='".wp_create_nonce('GoogleAuthenticatoraction')."';\n";
193
  echo <<<ENDOFJS
194
  jQuery('#GA_newsecret').bind('click', function() {
@@ -198,7 +218,7 @@ function GoogleAuthenticator_profile_personal_options() {
198
  jQuery.post(ajaxurl, data, function(response) {
199
  jQuery('#GA_secret').val(response['new-secret']);
200
  chl=escape("otpauth://totp/"+jQuery('#GA_description').val()+"?secret="+jQuery('#GA_secret').val());
201
- qrcodeurl="http://chart.apis.google.com/chart?cht=qr&chs=300x300&chld=H|0&chl="+chl;
202
  jQuery('#GA_QRCODE').attr('src',qrcodeurl);
203
  jQuery('#GA_QR_INFO').show('slow');
204
  });
@@ -206,7 +226,7 @@ function GoogleAuthenticator_profile_personal_options() {
206
 
207
  jQuery('#GA_description').bind('focus blur change keyup', function() {
208
  chl=escape("otpauth://totp/"+jQuery('#GA_description').val()+"?secret="+jQuery('#GA_secret').val());
209
- qrcodeurl="http://chart.apis.google.com/chart?cht=qr&chs=300x300&chld=H|0&chl="+chl;
210
  jQuery('#GA_QRCODE').attr('src',qrcodeurl);
211
  });
212
 
@@ -218,43 +238,37 @@ ENDOFJS;
218
  /**
219
  * Form handling of Google Authenticator options added to personal profile page (user editing his own profile)
220
  */
221
- function GoogleAuthenticator_personal_options_update() {
222
  global $user_id;
223
 
224
  $GA_enabled = trim( $_POST['GA_enabled'] );
225
  $GA_secret = trim( $_POST['GA_secret'] );
226
  $GA_description = trim( $_POST['GA_description'] );
227
 
228
- if ($GA_enabled !="") {
229
- $GA_enabled="enabled";
230
- } else {
231
- $GA_enabled="disabled";
232
- }
233
 
234
  update_user_option( $user_id, 'googleauthenticator_enabled', $GA_enabled, true );
235
  update_user_option( $user_id, 'googleauthenticator_secret', $GA_secret, true );
236
  update_user_option( $user_id, 'googleauthenticator_description', $GA_description, true );
237
-
238
  }
239
 
240
  /**
241
  * Extend profile page with ability to enable/disable Google Authenticator authentication requirement.
242
  * Used by an administrator when editing other users.
243
  */
244
- function GoogleAuthenticator_edit_user_profile() {
245
  global $user_id;
246
  $GA_enabled = trim( get_user_option( 'googleauthenticator_enabled', $user_id ) );
247
- echo "<h3>".__('Google Authenticator settings','google-auth')."</h3>\n";
248
  echo "<table class=\"form-table\">\n";
249
  echo "<tbody>\n";
250
  echo "<tr>\n";
251
- echo "<th scope=\"row\">".__('Active','google-auth')."</th>\n";
252
  echo "<td>\n";
253
- echo "<div><input name=\"GA_enabled\" id=\"GA_enabled\" class=\"tog\" type=\"checkbox\"";
254
- if ( $GA_enabled == 'enabled' ) {
255
- echo ' checked ';
256
- }
257
- echo "/>\n";
258
  echo "</td>\n";
259
  echo "</tr>\n";
260
  echo "</tbody>\n";
@@ -264,77 +278,41 @@ function GoogleAuthenticator_edit_user_profile() {
264
  /**
265
  * Form handling of Google Authenticator options on edit profile page (admin user editing other user)
266
  */
267
- function GoogleAuthenticator_edit_user_profile_update() {
268
  global $user_id;
269
 
270
  $GA_enabled = trim( $_POST['GA_enabled'] );
271
- if ( $GA_enabled != '' ) {
272
- update_user_option( $user_id, 'googleauthenticator_enabled', 'enabled', true );
273
- } else {
274
- update_user_option( $user_id, 'googleauthenticator_enabled', 'disabled', true );
275
- }
 
 
276
  }
277
 
278
 
279
  /**
280
  * AJAX callback function used to generate new secret
281
  */
282
- function GoogleAuthenticator_callback() {
283
  global $user_id;
284
 
285
  // Some AJAX security
286
- check_ajax_referer('GoogleAuthenticatoraction', 'nonce');
287
 
288
  // Create new secret, using the users password hash as input for further hashing
289
- $secret=GoogleAuthenticator_create_secret( get_user_option( 'user_pass', $user_id ) );
290
 
291
- $result=array('new-secret'=>$secret);
292
- header( "Content-Type: application/json" );
293
  echo json_encode( $result );
294
 
295
  // die() is required to return a proper result
296
  die();
297
  }
298
 
 
299
 
300
- /**
301
- * Does the PHP installation have what it takes to use this plugin ?
302
- */
303
- function GoogleAuthenticator_check_requirements() {
304
-
305
- // is the SHA-1 hashing available ?
306
- $GoogleAuthenticatorAlgos = hash_algos();
307
- if ( ! in_array( "sha1", $GoogleAuthenticatorAlgos ) ) {
308
- return false;
309
- }
310
- // is the SHA-256 hashing available ?
311
- $GoogleAuthenticatorAlgos = hash_algos();
312
- if ( ! in_array( "sha256", $GoogleAuthenticatorAlgos ) ) {
313
- return false;
314
- }
315
- return true;
316
- }
317
-
318
- /**
319
- * Prevent activation of the plugin if the PHP installation doesn't meet the requirements.
320
- */
321
- function GoogleAuthenticator_activate() {
322
- if ( ! GoogleAuthenticator_check_requirements()) {
323
- die( __('Google Authenticator: Something is missing, this plugin requires the SHA1 & SHA256 Hashing algorithms to be present in your PHP installation.', 'google-auth') );
324
- }
325
- }
326
-
327
- // Initialization and Hooks
328
- add_action('personal_options_update','GoogleAuthenticator_personal_options_update');
329
- add_action('profile_personal_options','GoogleAuthenticator_profile_personal_options');
330
- add_action('edit_user_profile','GoogleAuthenticator_edit_user_profile');
331
- add_action('edit_user_profile_update','GoogleAuthenticator_edit_user_profile_update');
332
- add_action('login_form', 'GoogleAuthenticator_loginform');
333
- add_action('wp_ajax_GoogleAuthenticator_action', 'GoogleAuthenticator_callback');
334
-
335
- add_filter('wp_authenticate_user','GoogleAuthenticator_check_otp');
336
-
337
- register_activation_hook( __FILE__, 'GoogleAuthenticator_activate' );
338
-
339
- load_plugin_textdomain('google-auth', false , dirname( plugin_basename(__FILE__)).'/lang' );
340
  ?>
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.30
8
  Author URI: http://henrik.schack.dk/
9
+ Compatibility: WordPress 3.2-RC2
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
 
18
  ----------------------------------------------------------------------------
19
 
34
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35
  */
36
 
37
+ class GoogleAuthenticator {
38
 
39
+ static $instance; // to store a reference to the plugin, allows other plugins to remove actions
40
+
41
+ /**
42
+ * Constructor, entry point of the plugin
43
+ */
44
+ function __construct() {
45
+ self::$instance = $this;
46
+ add_action( 'init', array( $this, 'init' ) );
47
+ }
48
+
49
+ /**
50
+ * Initialization, Hooks, and localization
51
+ */
52
+ function init() {
53
+ require_once( 'base32.php' );
54
+
55
+ add_action( 'login_form', array( $this, 'loginform' ) );
56
+ add_filter( 'wp_authenticate_user', array( $this, 'check_otp' ) );
57
+
58
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
59
+ add_action( 'wp_ajax_GoogleAuthenticator_action', array( $this, 'ajax_callback' ) );
60
+
61
+ add_action( 'personal_options_update', array( $this, 'personal_options_update' ) );
62
+ add_action( 'profile_personal_options', array( $this, 'profile_personal_options' ) );
63
+ add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) );
64
+ add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) );
65
+
66
+ load_plugin_textdomain( 'google-authenticator', false, basename( dirname( __FILE__ ) ) . '/lang' );
67
+ }
68
 
69
  /**
70
  * Check the verification code entered by the user.
71
  */
72
+ function verify( $secretkey, $thistry ) {
73
 
74
+ $tm = floor( time() / 30 );
75
 
76
  $secretkey=Base32::decode($secretkey);
77
  // Keys from 30 seconds before and after are valid aswell.
79
  // Pack time into binary string
80
  $time=chr(0).chr(0).chr(0).chr(0).pack('N*',$tm+$i);
81
  // Hash it with users secret key
82
+ $hm = hash_hmac( 'SHA1', $time, $secretkey, true );
83
  // Use last nipple of result as index/offset
84
  $offset = ord(substr($hm,-1)) & 0x0F;
85
  // grab 4 bytes of the result
89
  $value=$value[1];
90
  // Only 32 bits
91
  $value = $value & 0x7FFFFFFF;
92
+ $value = $value % 1000000;
93
+ if ( $value == $thistry ) {
94
  return true;
95
+ }
96
  }
97
  return false;
98
  }
99
 
100
  /**
101
+ * Create a new random secret for the Google Authenticator app.
102
+ * 16 characters, randomly chosen from the allowed Base32 characters
103
+ * equals 10 bytes = 80 bits, as 256^10 = 32^16 = 2^80
 
104
  */
105
+ function create_secret() {
106
+ $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; // allowed characters in Base32
107
+ $secret = '';
108
+ for ( $i = 0; $i < 16; $i++ ) {
109
+ $secret .= substr( $chars, wp_rand( 0, strlen( $chars ) - 1 ), 1 );
110
+ }
111
+ return $secret;
112
  }
113
 
114
 
115
  /**
116
  * Add verification code field to login form.
117
  */
118
+ function loginform() {
119
+ echo "\t<p>\n";
120
+ echo "\t\t<label><a href=\"http://code.google.com/p/google-authenticator/\" target=\"_blank\" title=\"".__('If you don\'t have Google Authenticator enabled for your WordPress account, leave this field empty.','google-authenticator')."\">".__('Google Authenticator code','google-authenticator')."</a><span id=\"google-auth-info\"></span><br />\n";
121
+ echo "\t\t<input type=\"password\" name=\"otp\" id=\"user_email\" class=\"input\" value=\"\" size=\"20\" tabindex=\"25\" /></label>\n";
122
+ echo "\t</p>\n";
123
  }
124
 
125
 
129
  * @param wordpressuser
130
  * @return user/loginstatus
131
  */
132
+ function check_otp( $user ) {
133
 
134
  // Does the user have the Google Authenticator enabled ?
135
  if ( trim(get_user_option('googleauthenticator_enabled',$user->ID)) == 'enabled' ) {
141
  $otp = intval( trim( $_POST[ 'otp' ] ) );
142
 
143
  // Valid code ?
144
+ if ( ! $this->verify( $GA_secret, $otp ) )
145
+ return new WP_Error( 'invalid_google_authenticator_token', __( '<strong>ERROR</strong>: The Google Authenticator code is incorrect or has expired.', 'google-authenticator' ) );
 
146
  }
147
  return $user;
148
  }
151
  /**
152
  * Extend personal profile page with Google Authenticator settings.
153
  */
154
+ function profile_personal_options() {
155
  global $user_id, $is_profile_page;
156
 
157
  $GA_secret =trim( get_user_option( 'googleauthenticator_secret', $user_id ) );
159
  $GA_description =trim( get_user_option( 'googleauthenticator_description', $user_id ) );
160
 
161
  // In case the user has no secret ready (new install), we create one.
162
+ if ( '' == $GA_secret )
163
+ $GA_secret = $this->create_secret();
 
164
 
165
+ // Use "WordPress Blog" as default description
166
+ if ( '' == $GA_description )
167
+ $GA_description = __( 'WordPress Blog', 'google-authenticator' );
 
168
 
169
+ echo "<h3>".__( 'Google Authenticator Settings', 'google-authenticator' )."</h3>\n";
170
 
171
  echo "<table class=\"form-table\">\n";
172
  echo "<tbody>\n";
173
  echo "<tr>\n";
174
+ echo "<th scope=\"row\">".__( 'Active', 'google-authenticator' )."</th>\n";
175
  echo "<td>\n";
176
+ echo "<div><input name=\"GA_enabled\" id=\"GA_enabled\" class=\"tog\" type=\"checkbox\"" . checked( $GA_enabled, 'enabled', false ) . "/></div>\n";
 
 
 
 
 
 
 
177
  echo "</td>\n";
178
  echo "</tr>\n";
179
 
180
  // Create URL for the Google charts QR code generator.
181
+ $chl = urlencode( "otpauth://totp/{$GA_description}?secret={$GA_secret}" );
182
+ $qrcodeurl = "https://chart.googleapis.com/chart?cht=qr&amp;chs=300x300&amp;chld=H|0&amp;chl={$chl}";
183
 
184
  if ( $is_profile_page || IS_PROFILE_PAGE ) {
185
  echo "<tr>\n";
186
+ echo "<th><label for=\"GA_description\">".__('Description','google-authenticator')."</label></th>\n";
187
+ echo "<td><input name=\"GA_description\" id=\"GA_description\" value=\"{$GA_description}\" type=\"text\" /><span class=\"description\">".__(' Description that you\'ll see in the Google Authenticator app on your phone.','google-authenticator')."</span><br /></td>\n";
188
  echo "</tr>\n";
189
 
190
  echo "<tr>\n";
191
+ echo "<th><label for=\"GA_secret\">".__('Secret','google-authenticator')."</label></th>\n";
192
  echo "<td>\n";
193
+ echo "<input name=\"GA_secret\" id=\"GA_secret\" value=\"{$GA_secret}\" readonly=\"true\" type=\"text\" />";
194
+ echo "<input name=\"GA_newsecret\" id=\"GA_newsecret\" value=\"".__("Create new secret",'google-authenticator')."\" type=\"button\" class=\"button\" />";
195
+ echo "<input name=\"show_qr\" id=\"show_qr\" value=\"".__("Show/Hide QR code",'google-authenticator')."\" type=\"button\" class=\"button\" onclick=\"jQuery('#GA_QR_INFO').toggle('slow');\" />";
196
  echo "</td>\n";
197
  echo "</tr>\n";
198
 
199
  echo "<tr>\n";
200
  echo "<th></th>\n";
201
  echo "<td><div id=\"GA_QR_INFO\" style=\"display: none\" >";
202
+ echo "<img id=\"GA_QRCODE\" src=\"{$qrcodeurl}\" alt=\"QR Code\"/>";
203
+ echo '<span class="description"><br/> ' . __( 'Scan this with the Google Authenticator app.', 'google-authenticator' ) . '</span>';
204
  echo "</div></td>\n";
205
  echo "</tr>\n";
206
 
209
 
210
  echo "</tbody></table>\n";
211
  echo "<script type=\"text/javascript\">\n";
 
212
  echo "var GAnonce='".wp_create_nonce('GoogleAuthenticatoraction')."';\n";
213
  echo <<<ENDOFJS
214
  jQuery('#GA_newsecret').bind('click', function() {
218
  jQuery.post(ajaxurl, data, function(response) {
219
  jQuery('#GA_secret').val(response['new-secret']);
220
  chl=escape("otpauth://totp/"+jQuery('#GA_description').val()+"?secret="+jQuery('#GA_secret').val());
221
+ qrcodeurl="https://chart.googleapis.com/chart?cht=qr&chs=300x300&chld=H|0&chl="+chl;
222
  jQuery('#GA_QRCODE').attr('src',qrcodeurl);
223
  jQuery('#GA_QR_INFO').show('slow');
224
  });
226
 
227
  jQuery('#GA_description').bind('focus blur change keyup', function() {
228
  chl=escape("otpauth://totp/"+jQuery('#GA_description').val()+"?secret="+jQuery('#GA_secret').val());
229
+ qrcodeurl="https://chart.googleapis.com/chart?cht=qr&chs=300x300&chld=H|0&chl="+chl;
230
  jQuery('#GA_QRCODE').attr('src',qrcodeurl);
231
  });
232
 
238
  /**
239
  * Form handling of Google Authenticator options added to personal profile page (user editing his own profile)
240
  */
241
+ function personal_options_update() {
242
  global $user_id;
243
 
244
  $GA_enabled = trim( $_POST['GA_enabled'] );
245
  $GA_secret = trim( $_POST['GA_secret'] );
246
  $GA_description = trim( $_POST['GA_description'] );
247
 
248
+ if ( '' == $GA_enabled )
249
+ $GA_enabled = 'disabled';
250
+ else
251
+ $GA_enabled = 'enabled';
 
252
 
253
  update_user_option( $user_id, 'googleauthenticator_enabled', $GA_enabled, true );
254
  update_user_option( $user_id, 'googleauthenticator_secret', $GA_secret, true );
255
  update_user_option( $user_id, 'googleauthenticator_description', $GA_description, true );
 
256
  }
257
 
258
  /**
259
  * Extend profile page with ability to enable/disable Google Authenticator authentication requirement.
260
  * Used by an administrator when editing other users.
261
  */
262
+ function edit_user_profile() {
263
  global $user_id;
264
  $GA_enabled = trim( get_user_option( 'googleauthenticator_enabled', $user_id ) );
265
+ echo "<h3>".__('Google Authenticator Settings','google-authenticator')."</h3>\n";
266
  echo "<table class=\"form-table\">\n";
267
  echo "<tbody>\n";
268
  echo "<tr>\n";
269
+ echo "<th scope=\"row\">".__('Active','google-authenticator')."</th>\n";
270
  echo "<td>\n";
271
+ echo "<div><input name=\"GA_enabled\" id=\"GA_enabled\" class=\"tog\" type=\"checkbox\"" . checked( $GA_enabled, 'enabled', false ) . "/>\n";
 
 
 
 
272
  echo "</td>\n";
273
  echo "</tr>\n";
274
  echo "</tbody>\n";
278
  /**
279
  * Form handling of Google Authenticator options on edit profile page (admin user editing other user)
280
  */
281
+ function edit_user_profile_update() {
282
  global $user_id;
283
 
284
  $GA_enabled = trim( $_POST['GA_enabled'] );
285
+
286
+ if ( '' == $GA_enabled )
287
+ $GA_enabled = 'disabled';
288
+ else
289
+ $GA_enabled = 'enabled';
290
+
291
+ update_user_option( $user_id, 'googleauthenticator_enabled', $GA_enabled, true );
292
  }
293
 
294
 
295
  /**
296
  * AJAX callback function used to generate new secret
297
  */
298
+ function ajax_callback() {
299
  global $user_id;
300
 
301
  // Some AJAX security
302
+ check_ajax_referer( 'GoogleAuthenticatoraction', 'nonce' );
303
 
304
  // Create new secret, using the users password hash as input for further hashing
305
+ $secret = $this->create_secret();
306
 
307
+ $result = array( 'new-secret' => $secret );
308
+ header( 'Content-Type: application/json' );
309
  echo json_encode( $result );
310
 
311
  // die() is required to return a proper result
312
  die();
313
  }
314
 
315
+ } // end class
316
 
317
+ new GoogleAuthenticator;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  ?>
lang/google-authenticator-de_DE.mo ADDED
Binary file
lang/google-authenticator-de_DE.po ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Google Authenticator 0.30\n"
4
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/google-authenticator\n"
5
+ "POT-Creation-Date: 2011-05-17 19:38:36+00:00\n"
6
+ "PO-Revision-Date: 2011-06-25 16:20+0100\n"
7
+ "Last-Translator: Tobias Bäthge <wordpress@tobias.baethge.com>\n"
8
+ "Language-Team: \n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
+ "X-Poedit-Language: \n"
14
+ "X-Poedit-Country: \n"
15
+ "X-Poedit-SourceCharset: utf-8\n"
16
+ "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
17
+ "X-Poedit-Basepath: \n"
18
+ "X-Poedit-Bookmarks: \n"
19
+ "X-Poedit-SearchPath-0: .\n"
20
+ "X-Textdomain-Support: yes"
21
+
22
+ #: google-authenticator.php:118
23
+ #@ google-authenticator
24
+ msgid "Google Authenticator code"
25
+ msgstr "&quot;Google Authenticator&quot;-Code"
26
+
27
+ #: google-authenticator.php:172
28
+ #: google-authenticator.php:267
29
+ #@ google-authenticator
30
+ msgid "Active"
31
+ msgstr "Aktivieren"
32
+
33
+ #: google-authenticator.php:184
34
+ #@ google-authenticator
35
+ msgid "Description"
36
+ msgstr "Beschreibung"
37
+
38
+ #: google-authenticator.php:189
39
+ #@ google-authenticator
40
+ msgid "Secret"
41
+ msgstr "Geheimschlüssel"
42
+
43
+ #: google-authenticator.php:192
44
+ #@ google-authenticator
45
+ msgid "Create new secret"
46
+ msgstr "Neuen Geheimschlüssel erzeugen"
47
+
48
+ #: google-authenticator.php:193
49
+ #@ google-authenticator
50
+ msgid "Show/Hide QR code"
51
+ msgstr "QR-Code anzeigen/verstecken"
52
+
53
+ #. translators: plugin header field 'Name'
54
+ #: google-authenticator.php:0
55
+ #@ google-authenticator
56
+ msgid "Google Authenticator"
57
+ msgstr "Google Authenticator"
58
+
59
+ #. translators: plugin header field 'PluginURI'
60
+ #: google-authenticator.php:0
61
+ #@ google-authenticator
62
+ msgid "http://henrik.schack.dk/google-authenticator-for-wordpress"
63
+ msgstr "http://henrik.schack.dk/google-authenticator-for-wordpress"
64
+
65
+ #. translators: plugin header field 'Author'
66
+ #: google-authenticator.php:0
67
+ #@ google-authenticator
68
+ msgid "Henrik Schack"
69
+ msgstr "Henrik Schack"
70
+
71
+ #. translators: plugin header field 'AuthorURI'
72
+ #: google-authenticator.php:0
73
+ #@ google-authenticator
74
+ msgid "http://henrik.schack.dk/"
75
+ msgstr "http://henrik.schack.dk/"
76
+
77
+ #. translators: plugin header field 'Version'
78
+ #: google-authenticator.php:0
79
+ #@ google-authenticator
80
+ msgid "0.30"
81
+ msgstr "0.30"
82
+
83
+ #: google-authenticator.php:143
84
+ #@ google-authenticator
85
+ msgid "<strong>ERROR</strong>: The Google Authenticator code is incorrect or has expired."
86
+ msgstr "<strong>FEHLER</strong>: Der eingegebene &quot;Google Authenticator&quot;-Code ist falsch oder abgelaufen."
87
+
88
+ #: google-authenticator.php:165
89
+ #@ google-authenticator
90
+ msgid "WordPress Blog"
91
+ msgstr "WordPress-Blog"
92
+
93
+ #: google-authenticator.php:167
94
+ #: google-authenticator.php:263
95
+ #@ google-authenticator
96
+ msgid "Google Authenticator Settings"
97
+ msgstr "Einstellungen zu Google Authenticator"
98
+
99
+ #: google-authenticator.php:201
100
+ #@ google-authenticator
101
+ msgid "Scan this with the Google Authenticator app."
102
+ msgstr "Scanne diesen QR-Code mit der &quot;Google Authenticator&quot;-App deines Smartphones."
103
+
104
+ #: google-authenticator.php:118
105
+ #@ google-authenticator
106
+ msgid "If you don't have Google Authenticator enabled for your WordPress account, leave this field empty."
107
+ msgstr "Falls die Nutzung von &quot;Google Authenticator&quot; für dieses WordPress-Konto nicht aktiviert ist, dieses Feld leer lassen."
108
+
109
+ #: google-authenticator.php:185
110
+ #@ google-authenticator
111
+ msgid " Description that you'll see in the Google Authenticator app on your phone."
112
+ msgstr "Beschreibung, die in der &quot;Google Authenticator&quot;-App auf dem Smartphone angezeigt wird."
113
+
114
+ #. translators: plugin header field 'Description'
115
+ #: google-authenticator.php:0
116
+ #@ google-authenticator
117
+ msgid "Two-Factor Authentication for WordPress using the Android/iPhone/Blackberry app as One Time Password generator."
118
+ msgstr "Zwei-Faktor-Authentifizierung für WordPress mit der &quot;Google Authenticator&quot;-App für Android/iPhone/Blackberry"
119
+
readme.txt CHANGED
@@ -3,59 +3,60 @@ Contributors: Henrik.Schack
3
  Donate Link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=CA36JVKMLE9EA&lc=DK&item_number=Google%20Authenticator&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted
4
  Tags: authentication,otp,password,security,login,android,iphone,blackberry
5
  Requires at least: 3.1.2
6
- Tested up to: 3.1.2
7
- Stable tag: 0.20
8
 
9
- Google Authenticator for your Wordpress blog.
10
 
11
  == Description ==
12
 
13
- The Google Authenticator plugin for WordPress gives you multifactor authentication using the Google Authenticator app for Android/iPhone/Blackberry.
14
 
15
- If you're security aware you may allready have the Google Authenticator app installed, using it for multifactor authentication on your Gmail or Google Apps account.
16
 
17
- The multifactor authentication requirement can be enabled on a per user basis, You could enable it for your administrator account, but login as usual with less privileged accounts.
18
-
19
-
20
- ** Notice: This plugin requires the SHA1 & SHA256 hashing algorithms to be available in your PHP installation, it's not possible to activate the plugin without **
21
 
22
  == Installation ==
23
 
24
  1. Install and activate the plugin.
25
  2. Enter a description on the Users -> Profile and Personal options page, in the Google Authenticator section.
26
- 3. Scan the generated QR code with your phone, or enter the secret manually (remember to pick the time based one)
27
  4. Remember to hit the **Update profile** button at the bottom of the page before leaving the Personal options page.
28
- 4. That's it, your Wordpress blog is now a little more secure.
29
 
30
  == Frequently Asked Questions ==
31
 
32
- = Are there any special requirements for my Wordpress/PHP installation ? =
33
-
34
- Yes, your PHP installation needs the SHA1 & SHA256 hashing algorithms.
35
-
36
- = Can I use Google Authenticator for Wordpress with the Android/iPhone apps for Wordpress ? =
37
-
38
- No, that wont work, but you could create a special account for mobile usage and choose not to enable
39
- the Google Authenticator this account.
40
 
41
- = I want to update the secret, should I just scan the new QR code after creating a new secret ? =
42
 
43
- No you'll have to delete the existing account from your Google Authenticator app before you scan the new QR code, that is unless you
44
- change the description as well.
45
 
46
- = Sometimes I am unable to login using this plugin, the first code never works, what's wrong ? =
47
 
48
- The Google Authenticator verification codes are time based, so it's crucial the clock in your phone is accurate.
49
 
 
50
 
51
  == Screenshots ==
52
 
53
- 1. The enhanced loginbox.
54
  2. Google Authenticator section on the Profile and Personal options page.
55
  3. QR code on the Profile and Personal options page.
56
  4. Google Authenticator app on Android
57
 
58
  == Changelog ==
59
 
 
 
 
 
 
60
  = 0.20 =
61
  * Initial release
 
 
 
 
 
 
3
  Donate Link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=CA36JVKMLE9EA&lc=DK&item_number=Google%20Authenticator&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted
4
  Tags: authentication,otp,password,security,login,android,iphone,blackberry
5
  Requires at least: 3.1.2
6
+ Tested up to: 3.2-RC2
7
+ Stable tag: 0.30
8
 
9
+ Google Authenticator for your WordPress blog.
10
 
11
  == Description ==
12
 
13
+ The Google Authenticator plugin for WordPress gives you two-factor authentication using the Google Authenticator app for Android/iPhone/Blackberry.
14
 
15
+ If you are security aware, you may already have the Google Authenticator app installed on your smartphone, using it for two-factor authentication on your Gmail or Google Apps account.
16
 
17
+ The two-factor authentication requirement can be enabled on a per-user basis. You could enable it for your administrator account, but log in as usual with less privileged accounts.
 
 
 
18
 
19
  == Installation ==
20
 
21
  1. Install and activate the plugin.
22
  2. Enter a description on the Users -> Profile and Personal options page, in the Google Authenticator section.
23
+ 3. Scan the generated QR code with your phone, or enter the secret manually (remember to pick the time based one).
24
  4. Remember to hit the **Update profile** button at the bottom of the page before leaving the Personal options page.
25
+ 4. That's it, your WordPress blog is now a little more secure.
26
 
27
  == Frequently Asked Questions ==
28
 
29
+ = Can I use Google Authenticator for WordPress with the Android/iPhone apps for WordPress? =
 
 
 
 
 
 
 
30
 
31
+ No, that won't work, but you could create a special account for mobile usage and choose not to enable the usage of Google Authenticator for this account.
32
 
33
+ = I want to update the secret, should I just scan the new QR code after creating a new secret? =
 
34
 
35
+ No, you'll have to delete the existing account from the Google Authenticator app on your smartphone before you scan the new QR code, that is unless you change the description as well.
36
 
37
+ = Sometimes I am unable to log in using this plugin, the first code never works, what's wrong ? =
38
 
39
+ The Google Authenticator verification codes are time based, so it's crucial that the clock in your phone is accurate and in sync with the time on the server where your WordPress installation is hosted.
40
 
41
  == Screenshots ==
42
 
43
+ 1. The enhanced log-in box.
44
  2. Google Authenticator section on the Profile and Personal options page.
45
  3. QR code on the Profile and Personal options page.
46
  4. Google Authenticator app on Android
47
 
48
  == Changelog ==
49
 
50
+ = 0.30 =
51
+ * Code cleanup
52
+ * Changed generation of secret key, to no longer have requirement of SHA256 on the server
53
+ * German translation
54
+
55
  = 0.20 =
56
  * Initial release
57
+
58
+ == Credits ==
59
+
60
+ Thanks to:
61
+
62
+ [Tobias B�thge](http://tobias.baethge.com/) for his code rewrite and German translation.