diff --git a/class-two-factor-core.php b/class-two-factor-core.php index 9d2de9bf..cad24e48 100644 --- a/class-two-factor-core.php +++ b/class-two-factor-core.php @@ -149,7 +149,17 @@ public static function uninstall() { $option_keys = array(); - foreach ( self::get_providers_classes() as $provider_class ) { + $providers = self::get_default_providers(); + + /** This filter is documented in the get_providers() method */ + $additional_providers = apply_filters( 'two_factor_providers', $providers ); + + // Merge them with the default providers. + if ( ! empty( $additional_providers ) ) { + $providers = array_merge( $providers, $additional_providers ); + } + + foreach ( self::get_providers_classes( $providers ) as $provider_class ) { // Merge with provider-specific user meta keys. if ( method_exists( $provider_class, 'uninstall_user_meta_keys' ) ) { try { @@ -192,43 +202,28 @@ public static function uninstall() { * * @return array List of provider keys and paths to class files. */ - public static function get_providers_registered() { - $providers = array( + private static function get_default_providers() { + return array( 'Two_Factor_Email' => TWO_FACTOR_DIR . 'providers/class-two-factor-email.php', 'Two_Factor_Totp' => TWO_FACTOR_DIR . 'providers/class-two-factor-totp.php', 'Two_Factor_FIDO_U2F' => TWO_FACTOR_DIR . 'providers/class-two-factor-fido-u2f.php', 'Two_Factor_Backup_Codes' => TWO_FACTOR_DIR . 'providers/class-two-factor-backup-codes.php', 'Two_Factor_Dummy' => TWO_FACTOR_DIR . 'providers/class-two-factor-dummy.php', ); - - /** - * Filter the supplied providers. - * - * @param array $providers A key-value array where the key is the class name, and - * the value is the path to the file containing the class. - */ - $additional_providers = apply_filters( 'two_factor_providers', $providers ); - - // Merge them with the default providers. - if ( ! empty( $additional_providers ) ) { - return array_merge( $providers, $additional_providers ); - } - - return $providers; } /** - * Get the classnames for all registered providers. + * Get the classnames for specific providers. * - * Note some of these providers might not be enabled. + * @param array $providers List of paths to provider class files indexed by class names. * * @return array List of provider keys and classnames. */ - private static function get_providers_classes() { - $providers = self::get_providers_registered(); - + private static function get_providers_classes( $providers ) { foreach ( $providers as $provider_key => $path ) { - require_once $path; + if ( ! empty( $path ) && is_readable( $path ) ) { + require_once $path; + } $class = $provider_key; @@ -241,9 +236,9 @@ private static function get_providers_classes() { $class = apply_filters( "two_factor_provider_classname_{$provider_key}", $class, $path ); /** - * Confirm that it's been successfully included before instantiating. + * Confirm that it's been successfully included. */ - if ( method_exists( $class, 'get_instance' ) ) { + if ( class_exists( $class ) ) { $providers[ $provider_key ] = $class; } else { unset( $providers[ $provider_key ] ); @@ -261,7 +256,7 @@ private static function get_providers_classes() { * @return array */ public static function get_providers() { - $providers = self::get_providers_registered(); + $providers = self::get_default_providers(); /** * Filter the supplied providers. @@ -287,15 +282,14 @@ public static function get_providers() { } // Map provider keys to classes so that we can instantiate them. - $providers = array_intersect_key( self::get_providers_classes(), $providers ); + $providers = self::get_providers_classes( $providers ); + // TODO: Refactor this to avoid instantiating the provider instances every time this method is called. foreach ( $providers as $provider_key => $provider_class ) { - if ( method_exists( $provider_class, 'get_instance' ) ) { - try { - $providers[ $provider_key ] = call_user_func( array( $provider_class, 'get_instance' ) ); - } catch ( Exception $e ) { - unset( $providers[ $provider_key ] ); - } + try { + $providers[ $provider_key ] = call_user_func( array( $provider_class, 'get_instance' ) ); + } catch ( Exception $e ) { + unset( $providers[ $provider_key ] ); } } diff --git a/providers/class-two-factor-backup-codes.php b/providers/class-two-factor-backup-codes.php index 12601d5c..2a3345b4 100644 --- a/providers/class-two-factor-backup-codes.php +++ b/providers/class-two-factor-backup-codes.php @@ -214,6 +214,25 @@ public function user_options( $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 @@ public static function codes_remaining_for_user( $user ) { */ 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 ); + ?> -


+

- +

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 @@ public function user_token_ttl( $user_id ) { * 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 @@ public function authentication_page( $user ) { $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'; ?>

- +

diff --git a/providers/class-two-factor-totp.php b/providers/class-two-factor-totp.php index 795ddd49..e94163f4 100644 --- a/providers/class-two-factor-totp.php +++ b/providers/class-two-factor-totp.php @@ -353,7 +353,7 @@ public function user_two_factor_options( $user ) { /* translators: Example auth code. */ $placeholder = sprintf( __( 'eg. %s', 'two-factor' ), '123456' ); ?> - +

@@ -690,7 +690,7 @@ public function authentication_page( $user ) {

- +