%s', $this->get_user_label(), __( 'Beta', 'wpdef' ) ); } /** * Get login label. * * @return string */ public function get_login_label(): string { return $this->get_label(); } /** * Get user label. * * @return string */ public function get_user_label(): string { return __( 'Biometric', 'wpdef' ); } /** * Get the desc of the provider. * * @return string */ public function get_description(): string { return __( 'Use fingerprint or facial recognition from external devices to authenticate login.', 'wpdef' ); } /** * Display auth method. * * @param WP_User $user WP_User object of the logged-in user. */ public function user_options( \WP_User $user ): void { $notices = [ [ 'type' => 'info', 'extra_class' => 'additional-2fa-method', 'style' => 'display: none', 'message' => __( 'Access from unregistered devices will be denied. To avoid this, consider setting up an additional authentication method.', 'wpdef' ), ], ]; $missed_requirement_message = $this->missed_requirement_message(); $user_has_admin_capability = current_user_can( 'manage_options' ); if ( $user_has_admin_capability ) { $notice_message = $missed_requirement_message['warning']; } else { $notice_message = __( 'Your site doesn\'t meet the requirements for biometric authentication. Please contact your site\'s administrator to fix this issue.', 'wpdef' ); } $all_server_requirement_passed = $missed_requirement_message['all_server_requirement_passed']; if ( $all_server_requirement_passed ) { $message = $missed_requirement_message['browser_message']; $extra_class = ' browser-notice '; } else { $message = $notice_message; $extra_class = ' has-server-error '; } $notices[] = [ 'type' => 'warning', 'extra_class' => $extra_class, 'style' => '', 'message' => $message, ]; $this->get_controller()->render_partial( 'two-fa/providers/biometric', [ 'notices' => $notices, ] ); } /** * Whether this 2FA provider is configured and available for the user specified. * * @param WP_User $user WP_User object of the logged-in user. * * @return bool */ public function is_available_for_user( \WP_User $user ): bool { return true; } /** * Authentication form markup. * * @return void */ public function authentication_form() { ?>

get( \WP_Defender\Controller\Webauthn::class ); $response = $webauthn_controller->verify_response( true ); if ( isset( $response['success'] ) && true === $response['success'] ) { return true; } else { $translations = $webauthn_controller->get_translations(); return new \WP_Error( 'opt_fail', $translations['login_failed'] ); } } /** * Create missed requirement message. * * Create dynamic message with boolean flag for all server requirement passed. * * @return array Dynamic message with boolean flag for all server requirement passed. */ private function missed_requirement_message(): array { $all_server_requirement_passed = true; $warning_core_message = ''; if ( ! $this->is_ssl() ) { $all_server_requirement_passed = false; $warning_core_message .= __( 'SSL certificate or HTTPS is not forced. ', 'wpdef' ); } $extension_warning_message = $this->get_extension_warning_message(); if ( $extension_warning_message !== '' ) { $all_server_requirement_passed = false; $warning_core_message .= $extension_warning_message; } $browser_extension_message = sprintf( __( 'The current browser version %s is not compatible with this feature, please update your browser version, or try a different one. ', 'wpdef' ), $this->get_browser_name() ); $warning_prefix = __( 'Your site doesn\'t meet the requirements for biometric authentication. ', 'wpdef' ); $warning_suffix = $this->get_warning_suffix(); $warning = $warning_prefix . $warning_core_message . $browser_extension_message . $warning_suffix; $browser_message = $warning_prefix . $browser_extension_message . $warning_suffix; return [ 'warning' => $warning, 'all_server_requirement_passed' => $all_server_requirement_passed, 'browser_message' => $browser_message, ]; } /** * Get customer support URL. * * @return string return customer support URL. */ private function customer_support_url(): string { $pro_url = 'https://wpmudev.com/hub2/support/#get-support'; return $pro_url; } /** * Get list of failed extensions. * * @return array Array of failed extensions or empty array if all extensions exists. */ private function get_failed_extension(): array { $failed_extensions = []; if ( ! $this->is_enabled_gmp() ) { $failed_extensions[] = 'GMP'; } if ( ! $this->is_enabled_mbstring() ) { $failed_extensions[] = 'MBSTRING'; } if ( ! $this->is_enabled_sodium() ) { $failed_extensions[] = 'SODIUM'; } return $failed_extensions; } /** * Concatenate multiple failed extensions. * * Form a comma separated with and before last element string from array of elements, if elements is more than two. * * @param array $extensions list of failed extensions. * * @return string Return concatenated string on success else empty string. */ private function concatenate_failed_extensions( array $extensions ): string { if ( count( $extensions ) === 1 ) { return $extensions[0]; } if ( count( $extensions ) > 1 ) { $last_extension = __( ' and ', 'wpdef' ) . array_pop( $extensions ); return implode( ', ', $extensions ) . $last_extension; } return ''; } /** * Create extension warning message * * @return string Warning message if extension not met the requirement or empty string for met requirement. */ private function get_extension_warning_message(): string { $message = ''; $failed_extensions = $this->get_failed_extension(); if ( count( $failed_extensions ) > 0 ) { $extension = __( 'extension', 'wpdef' ); $verb = __( 'is', 'wpdef' ); if ( count( $failed_extensions ) > 1 ) { $extension = __( 'extensions', 'wpdef' ); $verb = __( 'are', 'wpdef' ); } $extension_string = $this->concatenate_failed_extensions( $failed_extensions ); $message .= sprintf( __( 'The %1$s %2$s %3$s not active on your server. ', 'wpdef' ), $extension_string, $extension, $verb ); } return $message; } /** * Get browser name with optional version concatenated. * * @return string Browser name with or without version. */ private function get_browser_name( $with_version = true ): string { if ( ! function_exists( 'wp_check_browser_version' ) ) { include_once ABSPATH . 'wp-admin/includes/dashboard.php'; } $browser = wp_check_browser_version(); $browser_string = $browser['name'] . ( $with_version ? ' ' . $browser['version'] : '' ); return $browser_string; } /** * Determine the warning suffix. * * @return string Warning suffix sentence. */ private function get_warning_suffix(): string { $support_link = $this->customer_support_url(); $warning_suffix = ''; if ( ( new WPMUDEV() )->show_support_links() ) { $warning_suffix = sprintf( __( 'Still, having trouble? Open a support ticket.', 'wpdef' ), $support_link ); } return $warning_suffix; } }