PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.2.2
Defender Security – Malware Scanner, Login Security & Firewall v6.2.2
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / component / two-factor / providers / class-fallback-email.php

class-fallback-email.php in Defender Security – Malware Scanner, Login Security & Firewall 6.2.2, at src/component/two-factor/providers/class-fallback-email.php

201 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Fallback Email Two-Factor Authentication Provider.
4 *
5 * @package WP_Defender\Component\Two_Factor\Providers
6 */
7
8 namespace WP_Defender\Component\Two_Factor\Providers;
9
10 use WP_User;
11 use WP_Error;
12 use Calotes\Helper\HTTP;
13 use WP_Defender\Component\Crypt;
14 use WP_Defender\Component\Two_Factor\Two_Factor_Provider;
15
16 /**
17 * Handles fallback email for two-factor authentication.
18 *
19 * @since 2.8.0
20 */
21 class Fallback_Email extends Two_Factor_Provider {
22
23 /**
24 * 2fa provider slug.
25 *
26 * @var string
27 */
28 public static $slug = 'fallback-email';
29
30 /**
31 * User meta key to store the fallback email address.
32 *
33 * @var string
34 */
35 public const FALLBACK_EMAIL_KEY = 'defenderAuthEmail';
36
37 /**
38 * User meta key to store the backup code.
39 *
40 * @var string
41 */
42 public const FALLBACK_BACKUP_CODE_KEY = 'defenderBackupCode';
43
44 /**
45 * Constructor to add hooks related to the fallback email options.
46 */
47 public function __construct() {
48 add_action( 'wd_2fa_user_options_' . self::$slug, array( $this, 'user_options' ) );
49 }
50
51 /**
52 * Get the name of the provider.
53 *
54 * @return string
55 */
56 public function get_label(): string {
57 return esc_html__( 'Fallback Email', 'defender-security' );
58 }
59
60 /**
61 * Returns the login label for the fallback email provider.
62 *
63 * @return string
64 */
65 public function get_login_label(): string {
66 return $this->get_label();
67 }
68
69 /**
70 * Returns the user label for the fallback email provider.
71 *
72 * @return string
73 */
74 public function get_user_label(): string {
75 return esc_html__( 'Fallback email', 'defender-security' );
76 }
77
78 /**
79 * Get the desc of the provider.
80 *
81 * @return string
82 */
83 public function get_description(): string {
84 return esc_html__(
85 'If you ever lose your device, you can send a fallback passcode to this email address.',
86 'defender-security'
87 );
88 }
89
90 /**
91 * Display auth method.
92 *
93 * @param WP_User $user The user object.
94 */
95 public function user_options( WP_User $user ) {
96 $service = $this->get_component();
97 $class = $service->is_checked_enabled_provider_by_slug( $user, self::$slug ) ? '' : 'hidden';
98 $this->get_controller()->render_partial(
99 'two-fa/providers/fallback-email',
100 array(
101 'class' => $class,
102 'backup_email' => self::get_backup_email( $user->ID ),
103 )
104 );
105 }
106
107 /**
108 * Whether this 2FA provider is configured and available for the user specified.
109 *
110 * @param WP_User $user WP_User object of the logged-in user.
111 *
112 * @return bool
113 */
114 public function is_available_for_user( WP_User $user ): bool {
115 return true;
116 }
117
118 /**
119 * Outputs the form needed for authentication with this provider.
120 */
121 public function authentication_form() {
122 ?>
123 <p class="wpdef-2fa-label"><?php echo $this->get_login_label(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
124 <p class="wpdef-2fa-text">
125 <?php
126 echo esc_html__(
127 "We've sent a one-time passcode to your fallback email address. Enter it below to log in to your account.",
128 'defender-security'
129 );
130 ?>
131 </p>
132 <input type="text" autofocus value="" autocomplete="off" name="otp"/>
133 <button class="button button-primary float-r" type="submit">
134 <?php
135 esc_attr_e(
136 'Authenticate',
137 'defender-security'
138 );
139 ?>
140 </button>
141 <p class="wpdef-2fa-email-resend">
142 <button class="button button-secondary" type="button" id="wd-2fa-resend-code">
143 <?php
144 esc_html_e( 'Resend Code', 'defender-security' );
145 ?>
146 <img class="def-ajaxloader" src="<?php defender_asset_url( '/assets/img/spinner.svg', true ); ?>"/>
147 </button>
148 </p>
149 <?php
150 }
151
152 /**
153 * Retrieves the backup email address for the specified user.
154 *
155 * @param int|null $user_id The user ID. If null, the current user ID is used.
156 *
157 * @return bool|string The email address or false if not found.
158 */
159 public static function get_backup_email( $user_id = null ) {
160 if ( is_null( $user_id ) ) {
161 $user_id = get_current_user_id();
162 }
163 $email = get_user_meta( $user_id, self::FALLBACK_EMAIL_KEY, true );
164 if ( ! is_string( $email ) || '' === $email ) {
165 $user = get_user_by( 'id', $user_id );
166 if ( ! is_object( $user ) ) {
167 return false;
168 }
169 $email = $user->user_email;
170 }
171
172 return $email;
173 }
174
175 /**
176 * Whether this 2FA provider is configured and available for the user specified.
177 *
178 * @param WP_User $user The user object.
179 *
180 * @return bool|WP_Error
181 */
182 public function validate_authentication( $user ) {
183 $otp = HTTP::post( 'otp', '' );
184 $backup_code = get_user_meta( $user->ID, self::FALLBACK_BACKUP_CODE_KEY, true );
185 if ( isset( $backup_code['code'] ) && isset( $backup_code['time'] ) && Crypt::compare_lines( $backup_code['code'], wp_hash( $otp ) )
186 && strtotime( '+3 minutes', $backup_code['time'] ) > time()
187 ) {
188 delete_user_meta( $user->ID, self::FALLBACK_BACKUP_CODE_KEY );
189
190 return true;
191 } else {
192 $lockout_message = $this->get_component()->verify_attempt( $user->ID, self::$slug );
193
194 return new WP_Error(
195 'opt_fail',
196 '' === $lockout_message ? esc_html__( 'ERROR: Invalid passcode.', 'defender-security' ) : $lockout_message
197 );
198 }
199 }
200 }
201