PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 1.10.0
Fluent Support – Helpdesk & Customer Support Ticket System v1.10.0
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.0, at app/Hooks/Handlers/TwoFaHandler.php

203 lines 7.4 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' => $_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 $emailSubject = sprintf(__('Your Login code for %1s', 'fluent-support'), get_bloginfo('name'));
146
147 $pStart = '<p style="font-family: Arial, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">';
148
149 $message = $pStart . sprintf(__('Hello %s,', 'fluent-support'), $user->display_name) . '</p>' .
150 $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>' .
151 $pStart . '<b>' . sprintf(__('Verification Code: %s', 'fluent-security'), $data['twoFaCode']) . '</b></p>' .
152 '<br />' .
153 $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-security') . '</p>';
154
155 $message = apply_filters('fluent_support/signup_verification_email_body', $message, $data['twoFaCode'], $data);
156
157 $data = [
158 'body' => $message,
159 'pre_header' => __('Activate your account', 'fluent-security'),
160 'show_footer' => false
161 ];
162
163 $message = Helper::loadView('notification', $data);
164 $headers = array('Content-Type: text/html; charset=UTF-8');
165
166 \wp_mail($emailTo, $emailSubject, $message, $headers);
167 }
168
169 public function get2faForm($data = [])
170 {
171 ob_start();
172 ?>
173 <form
174 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);"
175 class="fs_2fa" id="fs_2fa_form">
176 <input type="hidden" name="login_hash" value="<?php echo esc_attr($data['login_hash']); ?>"/>
177 <div style="margin-bottom: 10px;">
178 <?php esc_html_e('Please check your email inbox and enter the two-factor verification code below:', 'fluent-support'); ?>
179 </div>
180 <div style="margin-bottom: 10px;">
181 <label for="login_passcode"><?php esc_html_e('Verification Code', 'fluent-support'); ?></label>
182 <div>
183 <input
184 style="font-size: 14px; padding: 8px; border: 1px solid #ccc; border-radius: 3px; width: 100%; box-sizing: border-box;"
185 placeholder="<?php esc_html_e('Login Code', 'fluent-support'); ?>" type="text" name="login_passcode"
186 id="login_passcode" class="input" size="20"/>
187 </div>
188 </div>
189 <div>
190 <button
191 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;"
192 id="fs_2fa_confirm" type="submit">
193 <?php esc_html_e('Verify and Login', 'fluent-support'); ?>
194 </button>
195 </div>
196 </form>
197 <?php
198
199 return ob_get_clean();
200 }
201
202 }
203