PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 1.10.2
Fluent Support – Helpdesk & Customer Support Ticket System v1.10.2
2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 All 68 releases
fluent-support / app / Hooks / Handlers / TwoFaHandler.php

TwoFaHandler.php in Fluent Support – Helpdesk & Customer Support Ticket System 1.10.2, at app/Hooks/Handlers/TwoFaHandler.php

207 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentSupport\App\Hooks\Handlers;
4
5 use FluentSupport\App\Models\Meta;
6 use FluentSupport\App\Services\Helper;
7 use FluentSupport\Framework\Support\Arr;
8
9
10 class TwoFaHandler
11 {
12 public function maybe2FaRedirect($user = null)
13 {
14 $return = $this->sendAndGet2FaConfirmFormUrl($user, 'both');
15
16 if (!$return) {
17 return false;
18 }
19
20 $getForm = $this->get2faForm($return);
21
22 wp_send_json([
23 'load_2fa' => 'yes',
24 'two_fa_form' => $getForm
25 ]);
26 }
27
28 public function sendAndGet2FaConfirmFormUrl($user, $return = 'url')
29 {
30 try {
31 $twoFaCode = str_pad(random_int(100123, 900987), 6, 0, STR_PAD_LEFT);
32 } catch (\Exception $e) {
33 $twoFaCode = str_pad(wp_rand(100123, 900987), 6, 0, STR_PAD_LEFT);
34 }
35
36 $string = $user->ID . '-' . wp_generate_uuid4() . wp_rand(1, 99999999);
37 $hash = wp_hash_password($string);
38 $hash = sanitize_title($hash, '', 'display');
39 $hash .= $user->ID . '-' . time();
40
41 $data = array(
42 'login_hash' => $hash,
43 'user_id' => $user->ID,
44 'status' => 'issued',
45 'ip_address' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '',
46 'use_type' => 'email_2_fa',
47 'user_email' => $user->user_email,
48 'two_fa_code_hash' => wp_hash_password($twoFaCode),
49 'valid_till' => date('Y-m-d H:i:s', current_time('timestamp') + 10 * 30),
50 'created_at' => current_time('mysql'),
51 'updated_at' => current_time('mysql'),
52 'used_count' => 0
53 );
54
55 $existingRecord = Meta::where('key', $hash)->first();
56
57 if ($existingRecord) {
58 $saveSettingsData = Meta::where('key', $hash)->update([
59 'value' => maybe_serialize($data)
60 ]);
61 } else {
62 $saveSettingsData = Meta::updateOrInsert([
63 'object_type' => 'fs_2fa',
64 'key' => $hash,
65 ], [
66 'value' => maybe_serialize($data)
67 ]);
68 }
69
70 if (!$saveSettingsData) {
71 return false;
72 }
73 $data['twoFaCode'] = $twoFaCode;
74 $this->send2FaEmail($data, $user, '');
75
76 return [
77 'redirect_to' => add_query_arg([
78 'fs_2fa' => 'email',
79 'login_hash' => $hash,
80 'action' => 'fs_2fa_email'
81 ], wp_login_url()),
82 'login_hash' => $hash,
83 ];
84 }
85
86 public function verify2FaEmailCode($data)
87 {
88 $redirectUrl = Helper::getPortalBaseUrl();
89
90 $code = $data['login_passcode'];
91 $hash = $data['login_hash'];
92
93 if (!$code || !$hash) {
94 wp_send_json([
95 'message' => __('Please provide a valid login code', 'fluent-support')
96 ], 423);
97 }
98
99 $logHash = Meta::where('key', $hash)->first();
100 $logHash = Helper::safeUnserialize($logHash->value, []);
101
102 if (!$logHash) {
103 wp_send_json([
104 'message' => __('Your provided code or url is not valid', 'fluent-support')
105 ], 423);
106 }
107 if (!wp_check_password($code, $logHash['two_fa_code_hash'])) {
108
109 $logHash['used_count'] += 1;
110
111 Meta::where('key', $hash)->update([
112 'value' => maybe_serialize($logHash)
113 ]);
114
115 return false;
116 }
117
118 if (strtotime($logHash['created_at']) < current_time('timestamp') - 600 || $logHash['used_count'] > 5 || $logHash['status'] != 'issued') {
119 wp_send_json([
120 'message' => __('Sorry, your login code has been expired. Please try to login again', 'fluent-support')
121 ], 423);
122 }
123 $user = get_user_by('email', $logHash['user_email']);
124
125 wp_clear_auth_cookie();
126 wp_set_current_user($user->ID);
127 wp_set_auth_cookie($user->ID);
128
129 if (is_user_logged_in()) {
130 $logHash['status'] = 'used';
131
132 Meta::where('key', $hash)->update([
133 'value' => maybe_serialize($logHash)
134 ]);
135 }
136
137 wp_send_json([
138 'redirect' => $redirectUrl
139 ], 200);
140 }
141
142 private function send2FaEmail($data, $user, $autoLoginUrl = false)
143 {
144 $emailTo = $user->user_email;
145 // translators: %1s is the site name
146 $emailSubject = sprintf(__('Your Login code for %1s', 'fluent-support'), get_bloginfo('name'));
147
148 $pStart = '<p style="font-family: Arial, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">';
149
150 // translators: %s is the user's display name
151 $message = $pStart . sprintf(__('Hello %s,', 'fluent-support'), $user->display_name) . '</p>' .
152 // translators: %s is the site name
153 $pStart . sprintf(__('Someone requested to login to %s and here is the Login code that you can use in the login form', 'fluent-support'), get_bloginfo('name')) . '</p>' .
154 // translators: %s is the two-factor authentication code
155 $pStart . '<b>' . sprintf(__('Verification Code: %s', 'fluent-support'), $data['twoFaCode']) . '</b></p>' .
156 '<br />' .
157 $pStart . __('This code is valid for 10 minutes and is meant to ensure the security of your account. If you did not initiate this request, please ignore this email.', 'fluent-support') . '</p>';
158
159 $message = apply_filters('fluent_support/signup_verification_email_body', $message, $data['twoFaCode'], $data);
160
161 $data = [
162 'body' => $message,
163 'pre_header' => __('Activate your account', 'fluent-support'),
164 'show_footer' => false
165 ];
166
167 $message = Helper::loadView('notification', $data);
168 $headers = array('Content-Type: text/html; charset=UTF-8');
169
170 \wp_mail($emailTo, $emailSubject, $message, $headers);
171 }
172
173 public function get2faForm($data = [])
174 {
175 ob_start();
176 ?>
177 <form
178 style="margin-top: 20px; padding: 20px; font-weight: 400; overflow: hidden; background: #f6f6f6; border: 1px solid #ccc; box-shadow: 0 0 10px rgba(0,0,0,.15);"
179 class="fs_2fa" id="fs_2fa_form">
180 <input type="hidden" name="login_hash" value="<?php echo esc_attr($data['login_hash']); ?>"/>
181 <div style="margin-bottom: 10px;">
182 <?php esc_html_e('Please check your email inbox and enter the two-factor verification code below:', 'fluent-support'); ?>
183 </div>
184 <div style="margin-bottom: 10px;">
185 <label for="login_passcode"><?php esc_html_e('Verification Code', 'fluent-support'); ?></label>
186 <div>
187 <input
188 style="font-size: 14px; padding: 8px; border: 1px solid #ccc; border-radius: 3px; width: 100%; box-sizing: border-box;"
189 placeholder="<?php esc_html_e('Login Code', 'fluent-support'); ?>" type="text" name="login_passcode"
190 id="login_passcode" class="input" size="20"/>
191 </div>
192 </div>
193 <div>
194 <button
195 style="display: inline-block; cursor: pointer; border: 0; background: #2271b1; color: #fff; text-decoration: none; text-shadow: none; min-height: 32px; padding: 8px 24px; font-size: 14px; border-radius: 3px;"
196 id="fs_2fa_confirm" type="submit">
197 <?php esc_html_e('Verify and Login', 'fluent-support'); ?>
198 </button>
199 </div>
200 </form>
201 <?php
202
203 return ob_get_clean();
204 }
205
206 }
207