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 | Google Authenticator |
Version | 0.30 |
Comparing to | |
See all releases |
Code changes from version 0.20 to 0.30
- google-authenticator.php +105 -127
- lang/google-authenticator-de_DE.mo +0 -0
- lang/google-authenticator-de_DE.po +119 -0
- readme.txt +26 -25
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:
|
6 |
Author: Henrik Schack
|
7 |
-
Version: 0.
|
8 |
Author URI: http://henrik.schack.dk/
|
9 |
-
Compatibility
|
10 |
-
Text Domain: google-
|
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 |
-
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
/**
|
40 |
* Check the verification code entered by the user.
|
41 |
*/
|
42 |
-
function
|
43 |
|
44 |
-
$tm=
|
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
|
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 =
|
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 |
-
*
|
73 |
-
*
|
74 |
-
* into the datastring.
|
75 |
*/
|
76 |
-
function
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
|
|
|
|
81 |
}
|
82 |
|
83 |
|
84 |
/**
|
85 |
* Add verification code field to login form.
|
86 |
*/
|
87 |
-
function
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
}
|
93 |
|
94 |
|
@@ -98,7 +129,7 @@ function GoogleAuthenticator_loginform() {
|
|
98 |
* @param wordpressuser
|
99 |
* @return user/loginstatus
|
100 |
*/
|
101 |
-
function
|
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 (!
|
114 |
-
return
|
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
|
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=
|
134 |
-
}
|
135 |
|
136 |
-
// Use "
|
137 |
-
if ($GA_description
|
138 |
-
$GA_description=__(
|
139 |
-
}
|
140 |
|
141 |
-
echo "<h3>".__( 'Google Authenticator
|
142 |
|
143 |
echo "<table class=\"form-table\">\n";
|
144 |
echo "<tbody>\n";
|
145 |
echo "<tr>\n";
|
146 |
-
echo "<th scope=\"row\">".__( 'Active', 'google-
|
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/
|
161 |
-
$qrcodeurl="
|
162 |
|
163 |
if ( $is_profile_page || IS_PROFILE_PAGE ) {
|
164 |
echo "<tr>\n";
|
165 |
-
echo "<th><label for=\"GA_description\">".__('Description','google-
|
166 |
-
echo "<td><input name=\"GA_description\" id=\"GA_description\" value=\"
|
167 |
echo "</tr>\n";
|
168 |
|
169 |
echo "<tr>\n";
|
170 |
-
echo "<th><label for=\"GA_secret\">".__('Secret','google-
|
171 |
echo "<td>\n";
|
172 |
-
echo "<input name=\"GA_secret\" id=\"GA_secret\" value=\"
|
173 |
-
echo "<input name=\"GA_newsecret\" id=\"GA_newsecret\" value=\"".__("Create new secret",'google-
|
174 |
-
echo "<input name=\"show_qr\" id=\"show_qr\" value=\"".__("Show/Hide QR code",'google-
|
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=\"
|
182 |
-
echo
|
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="
|
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="
|
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
|
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=
|
230 |
-
|
231 |
-
$GA_enabled=
|
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
|
245 |
global $user_id;
|
246 |
$GA_enabled = trim( get_user_option( 'googleauthenticator_enabled', $user_id ) );
|
247 |
-
echo "<h3>".__('Google Authenticator
|
248 |
echo "<table class=\"form-table\">\n";
|
249 |
echo "<tbody>\n";
|
250 |
echo "<tr>\n";
|
251 |
-
echo "<th scope=\"row\">".__('Active','google-
|
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
|
268 |
global $user_id;
|
269 |
|
270 |
$GA_enabled = trim( $_POST['GA_enabled'] );
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
|
|
|
|
276 |
}
|
277 |
|
278 |
|
279 |
/**
|
280 |
* AJAX callback function used to generate new secret
|
281 |
*/
|
282 |
-
function
|
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=
|
290 |
|
291 |
-
$result=array('new-secret'
|
292 |
-
header(
|
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&chs=300x300&chld=H|0&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 ""Google Authenticator"-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 "Google Authenticator"-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 "Google Authenticator"-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 "Google Authenticator" 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 "Google Authenticator"-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 "Google Authenticator"-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¤cy_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.
|
7 |
-
Stable tag: 0.
|
8 |
|
9 |
-
Google Authenticator for your
|
10 |
|
11 |
== Description ==
|
12 |
|
13 |
-
The Google Authenticator plugin for WordPress gives you
|
14 |
|
15 |
-
If you
|
16 |
|
17 |
-
The
|
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
|
29 |
|
30 |
== Frequently Asked Questions ==
|
31 |
|
32 |
-
=
|
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 |
-
|
42 |
|
43 |
-
|
44 |
-
change the description as well.
|
45 |
|
46 |
-
|
47 |
|
48 |
-
|
49 |
|
|
|
50 |
|
51 |
== Screenshots ==
|
52 |
|
53 |
-
1. The enhanced
|
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¤cy_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.
|