updated plugin Two Factor
version 0.13.0
This commit is contained in:
@ -40,7 +40,7 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider {
|
||||
add_action( 'two_factor_user_options_' . __CLASS__, array( $this, 'user_options' ) );
|
||||
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
||||
|
||||
return parent::__construct();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,6 +214,25 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider {
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the backup code length for a user.
|
||||
*
|
||||
* @param WP_User $user User object.
|
||||
*
|
||||
* @return int Number of characters.
|
||||
*/
|
||||
private function get_backup_code_length( $user ) {
|
||||
/**
|
||||
* Customize the character count of the backup codes.
|
||||
*
|
||||
* @var int $code_length Length of the backup code.
|
||||
* @var WP_User $user User object.
|
||||
*/
|
||||
$code_length = (int) apply_filters( 'two_factor_backup_code_length', 8, $user );
|
||||
|
||||
return $code_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates backup codes & updates the user meta.
|
||||
*
|
||||
@ -239,8 +258,10 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider {
|
||||
$codes_hashed = (array) get_user_meta( $user->ID, self::BACKUP_CODES_META_KEY, true );
|
||||
}
|
||||
|
||||
$code_length = $this->get_backup_code_length( $user );
|
||||
|
||||
for ( $i = 0; $i < $num_codes; $i++ ) {
|
||||
$code = $this->get_code();
|
||||
$code = $this->get_code( $code_length );
|
||||
$codes_hashed[] = wp_hash_password( $code );
|
||||
$codes[] = $code;
|
||||
unset( $code );
|
||||
@ -326,11 +347,15 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider {
|
||||
*/
|
||||
public function authentication_page( $user ) {
|
||||
require_once ABSPATH . '/wp-admin/includes/template.php';
|
||||
|
||||
$code_length = $this->get_backup_code_length( $user );
|
||||
$code_placeholder = str_repeat( 'X', $code_length );
|
||||
|
||||
?>
|
||||
<p class="two-factor-prompt"><?php esc_html_e( 'Enter a recovery code.', 'two-factor' ); ?></p><br/>
|
||||
<p class="two-factor-prompt"><?php esc_html_e( 'Enter a recovery code.', 'two-factor' ); ?></p>
|
||||
<p>
|
||||
<label for="authcode"><?php esc_html_e( 'Recovery Code:', 'two-factor' ); ?></label>
|
||||
<input type="text" inputmode="numeric" name="two-factor-backup-code" id="authcode" class="input authcode" value="" size="20" pattern="[0-9 ]*" placeholder="1234 5678" data-digits="8" />
|
||||
<input type="text" inputmode="numeric" name="two-factor-backup-code" id="authcode" class="input authcode" value="" size="20" pattern="[0-9 ]*" placeholder="<?php echo esc_attr( $code_placeholder ); ?>" data-digits="<?php echo esc_attr( $code_length ); ?>" />
|
||||
</p>
|
||||
<?php
|
||||
submit_button( __( 'Submit', 'two-factor' ) );
|
||||
@ -399,4 +424,15 @@ class Two_Factor_Backup_Codes extends Two_Factor_Provider {
|
||||
// Update the backup code master list.
|
||||
update_user_meta( $user->ID, self::BACKUP_CODES_META_KEY, $backup_codes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user meta keys to delete during plugin uninstall.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function uninstall_user_meta_keys() {
|
||||
return array(
|
||||
self::BACKUP_CODES_META_KEY,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ class Two_Factor_Dummy extends Two_Factor_Provider {
|
||||
*/
|
||||
protected function __construct() {
|
||||
add_action( 'two_factor_user_options_' . __CLASS__, array( $this, 'user_options' ) );
|
||||
return parent::__construct();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,7 +42,7 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
*/
|
||||
protected function __construct() {
|
||||
add_action( 'two_factor_user_options_' . __CLASS__, array( $this, 'user_options' ) );
|
||||
return parent::__construct();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,6 +63,22 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
return __( 'Send a code to your email', 'two-factor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the email token length.
|
||||
*
|
||||
* @return int Email token string length.
|
||||
*/
|
||||
private function get_token_length() {
|
||||
/**
|
||||
* Number of characters in the email token.
|
||||
*
|
||||
* @param int $token_length Number of characters in the email token.
|
||||
*/
|
||||
$token_length = (int) apply_filters( 'two_factor_email_token_length', 8 );
|
||||
|
||||
return $token_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the user token.
|
||||
*
|
||||
@ -72,7 +88,7 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
* @return string
|
||||
*/
|
||||
public function generate_token( $user_id ) {
|
||||
$token = $this->get_code();
|
||||
$token = $this->get_code( $this->get_token_length() );
|
||||
|
||||
update_user_meta( $user_id, self::TOKEN_META_KEY_TIMESTAMP, time() );
|
||||
update_user_meta( $user_id, self::TOKEN_META_KEY, wp_hash( $token ) );
|
||||
@ -146,10 +162,21 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
* Number of seconds the token is considered valid
|
||||
* after the generation.
|
||||
*
|
||||
* @deprecated 0.11.0 Use {@see 'two_factor_email_token_ttl'} instead.
|
||||
*
|
||||
* @param integer $token_ttl Token time-to-live in seconds.
|
||||
* @param integer $user_id User ID.
|
||||
*/
|
||||
return (int) apply_filters( 'two_factor_token_ttl', $token_ttl, $user_id );
|
||||
$token_ttl = (int) apply_filters_deprecated( 'two_factor_token_ttl', array( $token_ttl, $user_id ), '0.11.0', 'two_factor_email_token_ttl' );
|
||||
|
||||
/**
|
||||
* Number of seconds the token is considered valid
|
||||
* after the generation.
|
||||
*
|
||||
* @param integer $token_ttl Token time-to-live in seconds.
|
||||
* @param integer $user_id User ID.
|
||||
*/
|
||||
return (int) apply_filters( 'two_factor_email_token_ttl', $token_ttl, $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,12 +286,15 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
$this->generate_and_email_token( $user );
|
||||
}
|
||||
|
||||
$token_length = $this->get_token_length();
|
||||
$token_placeholder = str_repeat( 'X', $token_length );
|
||||
|
||||
require_once ABSPATH . '/wp-admin/includes/template.php';
|
||||
?>
|
||||
<p class="two-factor-prompt"><?php esc_html_e( 'A verification code has been sent to the email address associated with your account.', 'two-factor' ); ?></p>
|
||||
<p>
|
||||
<label for="authcode"><?php esc_html_e( 'Verification Code:', 'two-factor' ); ?></label>
|
||||
<input type="text" inputmode="numeric" name="two-factor-email-code" id="authcode" class="input authcode" value="" size="20" pattern="[0-9 ]*" placeholder="1234 5678" data-digits="8" />
|
||||
<input type="text" inputmode="numeric" name="two-factor-email-code" id="authcode" class="input authcode" value="" size="20" pattern="[0-9 ]*" autocomplete="one-time-code" placeholder="<?php echo esc_attr( $token_placeholder ); ?>" data-digits="<?php echo esc_attr( $token_length ); ?>" />
|
||||
<?php submit_button( __( 'Log In', 'two-factor' ) ); ?>
|
||||
</p>
|
||||
<p class="two-factor-email-resend">
|
||||
@ -287,7 +317,7 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
* Send the email code if missing or requested. Stop the authentication
|
||||
* validation if a new token has been generated and sent.
|
||||
*
|
||||
* @param WP_USer $user WP_User object of the logged-in user.
|
||||
* @param WP_User $user WP_User object of the logged-in user.
|
||||
* @return boolean
|
||||
*/
|
||||
public function pre_process_authentication( $user ) {
|
||||
@ -351,4 +381,16 @@ class Two_Factor_Email extends Two_Factor_Provider {
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user meta keys to delete during plugin uninstall.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function uninstall_user_meta_keys() {
|
||||
return array(
|
||||
self::TOKEN_META_KEY,
|
||||
self::TOKEN_META_KEY_TIMESTAMP,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -164,6 +164,10 @@ class Two_Factor_FIDO_U2F_Admin {
|
||||
* @param WP_User $user WP_User object of the logged-in user.
|
||||
*/
|
||||
public static function show_user_profile( $user ) {
|
||||
if ( ! Two_Factor_FIDO_U2F::is_supported_for_user( $user ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_nonce_field( "user_security_keys-{$user->ID}", '_nonce_user_security_keys' );
|
||||
$new_key = false;
|
||||
|
||||
@ -230,7 +234,7 @@ class Two_Factor_FIDO_U2F_Admin {
|
||||
* @static
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
* @return false
|
||||
* @return void|never
|
||||
*/
|
||||
public static function catch_submission( $user_id ) {
|
||||
if ( ! empty( $_REQUEST['do_new_security_key'] ) ) {
|
||||
@ -243,7 +247,7 @@ class Two_Factor_FIDO_U2F_Admin {
|
||||
|
||||
Two_Factor_FIDO_U2F::add_security_key( $user_id, $reg );
|
||||
} catch ( Exception $e ) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
delete_user_meta( $user_id, self::REGISTER_DATA_USER_META_KEY );
|
||||
|
@ -65,7 +65,7 @@ class Two_Factor_FIDO_U2F extends Two_Factor_Provider {
|
||||
|
||||
add_action( 'two_factor_user_options_' . __CLASS__, array( $this, 'user_options' ) );
|
||||
|
||||
return parent::__construct();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,7 +143,7 @@ class Two_Factor_FIDO_U2F extends Two_Factor_Provider {
|
||||
* @since 0.1-dev
|
||||
*
|
||||
* @param WP_User $user WP_User object of the logged-in user.
|
||||
* @return null
|
||||
* @return void
|
||||
*/
|
||||
public function authentication_page( $user ) {
|
||||
require_once ABSPATH . '/wp-admin/includes/template.php';
|
||||
@ -165,7 +165,7 @@ class Two_Factor_FIDO_U2F extends Two_Factor_Provider {
|
||||
?>
|
||||
<p><?php esc_html_e( 'An error occurred while creating authentication data.', 'two-factor' ); ?></p>
|
||||
<?php
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
wp_localize_script(
|
||||
@ -388,4 +388,17 @@ class Two_Factor_FIDO_U2F extends Two_Factor_Provider {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user meta keys to delete during plugin uninstall.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function uninstall_user_meta_keys() {
|
||||
return array(
|
||||
self::REGISTERED_KEY_USER_META_KEY,
|
||||
self::AUTH_DATA_USER_META_KEY,
|
||||
'_two_factor_fido_u2f_register_request', // From Two_Factor_FIDO_U2F_Admin which is not loaded during uninstall.
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,19 @@ abstract class Two_Factor_Provider {
|
||||
*/
|
||||
abstract public function is_available_for_user( $user );
|
||||
|
||||
/**
|
||||
* If this provider should be available for the user.
|
||||
*
|
||||
* @param WP_User|int $user WP_User object, user ID or null to resolve the current user.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_supported_for_user( $user = null ) {
|
||||
$providers = Two_Factor_Core::get_supported_providers_for_user( $user );
|
||||
|
||||
return isset( $providers[ static::class ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random eight-digit string to send out as an auth code.
|
||||
*
|
||||
@ -165,4 +178,24 @@ abstract class Two_Factor_Provider {
|
||||
|
||||
return (string) $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user meta keys that need to be deletated on plugin uninstall.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function uninstall_user_meta_keys() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the option keys that need to be deleted on plugin uninstall.
|
||||
*
|
||||
* Note: this method doesn't have access to the instantiated provider object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function uninstall_options() {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
add_action( 'two_factor_user_options_' . __CLASS__, array( $this, 'user_two_factor_options' ) );
|
||||
|
||||
return parent::__construct();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,7 +110,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
* Returns the name of the provider.
|
||||
*/
|
||||
public function get_label() {
|
||||
return _x( 'Authenticator app', 'Provider Label', 'two-factor' );
|
||||
return _x( 'Authenticator App', 'Provider Label', 'two-factor' );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,7 +119,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
* @since 0.9.0
|
||||
*/
|
||||
public function get_alternative_provider_label() {
|
||||
return __( 'Use your authenticator app', 'two-factor' );
|
||||
return __( 'Use your authenticator app for time-based one-time passwords (TOTP)', 'two-factor' );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,7 +142,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
/**
|
||||
* Rest API endpoint for handling deactivation of TOTP.
|
||||
*
|
||||
* @param WP_Rest_Request $request The Rest Request object.
|
||||
* @param WP_REST_Request $request The Rest Request object.
|
||||
* @return array Success array.
|
||||
*/
|
||||
public function rest_delete_totp( $request ) {
|
||||
@ -151,6 +151,10 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
|
||||
$this->delete_user_totp_key( $user_id );
|
||||
|
||||
if ( ! Two_Factor_Core::disable_provider_for_user( $user_id, 'Two_Factor_Totp' ) ) {
|
||||
return new WP_Error( 'db_error', __( 'Unable to disable TOTP provider for this user.', 'two-factor' ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
ob_start();
|
||||
$this->user_two_factor_options( $user );
|
||||
$html = ob_get_clean();
|
||||
@ -164,7 +168,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
/**
|
||||
* REST API endpoint for setting up TOTP.
|
||||
*
|
||||
* @param WP_Rest_Request $request The Rest Request object.
|
||||
* @param WP_REST_Request $request The Rest Request object.
|
||||
* @return WP_Error|array Array of data on success, WP_Error on error.
|
||||
*/
|
||||
public function rest_setup_totp( $request ) {
|
||||
@ -203,8 +207,8 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
/**
|
||||
* Generates a URL that can be used to create a QR code.
|
||||
*
|
||||
* @param WP_User $user The user to generate a URL for.
|
||||
* @param string $key The secret key.
|
||||
* @param WP_User $user The user to generate a URL for.
|
||||
* @param string $secret_key The secret key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -260,13 +264,13 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
* Display TOTP options on the user settings page.
|
||||
*
|
||||
* @param WP_User $user The current user being edited.
|
||||
* @return false
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function user_two_factor_options( $user ) {
|
||||
if ( ! isset( $user->ID ) ) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
$key = $this->get_user_totp_key( $user->ID );
|
||||
@ -318,6 +322,15 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
qr.make();
|
||||
|
||||
document.querySelector( '#two-factor-qr-code a' ).innerHTML = qr.createSvgTag( 5 );
|
||||
|
||||
// For accessibility, markup the SVG with a title and role.
|
||||
var svg = document.querySelector( '#two-factor-qr-code a svg' ),
|
||||
title = document.createElement( 'title' );
|
||||
|
||||
svg.role = 'image';
|
||||
svg.ariaLabel = <?php echo wp_json_encode( __( 'Authenticator App QR Code', 'two-factor' ) ); ?>;
|
||||
title.innerText = svg.ariaLabel;
|
||||
svg.appendChild( title );
|
||||
};
|
||||
|
||||
// Run now if the document is loaded, otherwise on DOMContentLoaded.
|
||||
@ -340,13 +353,20 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
/* translators: Example auth code. */
|
||||
$placeholder = sprintf( __( 'eg. %s', 'two-factor' ), '123456' );
|
||||
?>
|
||||
<input type="tel" name="two-factor-totp-authcode" id="two-factor-totp-authcode" class="input" value="" size="20" pattern="[0-9 ]*" placeholder="<?php echo esc_attr( $placeholder ); ?>" />
|
||||
<input type="text" inputmode="numeric" name="two-factor-totp-authcode" id="two-factor-totp-authcode" class="input" value="" size="20" pattern="[0-9 ]*" placeholder="<?php echo esc_attr( $placeholder ); ?>" autocomplete="off" />
|
||||
</label>
|
||||
<input type="submit" class="button totp-submit" name="two-factor-totp-submit" value="<?php esc_attr_e( 'Submit', 'two-factor' ); ?>" />
|
||||
</p>
|
||||
|
||||
<script>
|
||||
(function($){
|
||||
// Focus the auth code input when the checkbox is clicked.
|
||||
document.getElementById('enabled-Two_Factor_Totp').addEventListener('click', function(e) {
|
||||
if ( e.target.checked ) {
|
||||
document.getElementById('two-factor-totp-authcode').focus();
|
||||
}
|
||||
});
|
||||
|
||||
$('.totp-submit').click( function( e ) {
|
||||
e.preventDefault();
|
||||
var key = $('#two-factor-totp-key').val(),
|
||||
@ -359,6 +379,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
user_id: <?php echo wp_json_encode( $user->ID ); ?>,
|
||||
key: key,
|
||||
code: code,
|
||||
enable_provider: true,
|
||||
}
|
||||
} ).fail( function( response, status ) {
|
||||
var errorMessage = response.responseJSON.message || status,
|
||||
@ -370,8 +391,10 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
|
||||
$error.find('p').text( errorMessage );
|
||||
|
||||
$( '#enabled-Two_Factor_Totp' ).prop( 'checked', false );
|
||||
$('#two-factor-totp-authcode').val('');
|
||||
} ).then( function( response ) {
|
||||
$( '#enabled-Two_Factor_Totp' ).prop( 'checked', true );
|
||||
$( '#two-factor-totp-options' ).html( response.html );
|
||||
} );
|
||||
} );
|
||||
@ -398,6 +421,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
user_id: <?php echo wp_json_encode( $user->ID ); ?>,
|
||||
}
|
||||
} ).then( function( response ) {
|
||||
$( '#enabled-Two_Factor_Totp' ).prop( 'checked', false );
|
||||
$( '#two-factor-totp-options' ).html( response.html );
|
||||
} );
|
||||
} );
|
||||
@ -666,7 +690,7 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
</p>
|
||||
<p>
|
||||
<label for="authcode"><?php esc_html_e( 'Authentication Code:', 'two-factor' ); ?></label>
|
||||
<input type="text" inputmode="numeric" autocomplete="one-time-code" name="authcode" id="authcode" class="input authcode" value="" size="20" pattern="[0-9 ]*" placeholder="123 456" data-digits="<?php echo esc_attr( self::DEFAULT_DIGIT_COUNT ); ?>" />
|
||||
<input type="text" inputmode="numeric" autocomplete="one-time-code" name="authcode" id="authcode" class="input authcode" value="" size="20" pattern="[0-9 ]*" placeholder="123 456" autocomplete="one-time-code" data-digits="<?php echo esc_attr( self::DEFAULT_DIGIT_COUNT ); ?>" />
|
||||
</p>
|
||||
<script type="text/javascript">
|
||||
setTimeout( function(){
|
||||
@ -762,4 +786,16 @@ class Two_Factor_Totp extends Two_Factor_Provider {
|
||||
}
|
||||
return ( $a < $b ) ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user meta keys to delete during plugin uninstall.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function uninstall_user_meta_keys() {
|
||||
return array(
|
||||
self::SECRET_META_KEY,
|
||||
self::LAST_SUCCESSFUL_LOGIN_META_KEY,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user