PluginProbe ʕ •ᴥ•ʔ
Firebase Authentication / 1.7.0
Firebase Authentication v1.7.0
1.7.0 trunk 1.0.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.8 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9
firebase-authentication / class-mo-firebase-config.php
firebase-authentication Last commit date
admin 1 day ago includes 1 day ago languages 1 day ago public 1 day ago views 1 day ago README.txt 1 day ago class-mo-firebase-config.php 1 day ago class-mo-firebase-contact-us.php 1 day ago firebase-authentication.php 1 day ago index.php 1 day ago uninstall.php 1 day ago
class-mo-firebase-config.php
373 lines
1 <?php
2 /**
3 * File containing Firebase API calls
4 *
5 * @package Firebase Config
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Class containing Firebase API call functions
14 */
15 class Mo_Firebase_Config {
16 /**
17 * Initializing the test config control
18 */
19 public function __construct() {
20 add_action( 'init', array( $this, 'testconfig' ) );
21 }
22 /**
23 * Test configuration check
24 */
25 public function testconfig() {
26 if ( isset( $_REQUEST['mo_action'] ) && 'firebaselogin' === sanitize_text_field( wp_unslash( $_REQUEST['mo_action'] ) ) && isset( $_REQUEST['test'] ) && 'true' === sanitize_text_field( wp_unslash( $_REQUEST['test'] ) ) && isset( $_REQUEST['mo_firebase_auth_test_config_field'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['mo_firebase_auth_test_config_field'] ) ), 'mo_firebase_auth_test_config_form' ) ) {
27
28 $project_id = get_option( 'mo_firebase_auth_project_id' );
29 $api_key = get_option( 'mo_firebase_auth_api_key' );
30
31 $test_username = isset( $_POST['test_username'] ) ? sanitize_text_field( wp_unslash( $_POST['test_username'] ) ) : '';
32 $test_password = isset( $_POST['test_password'] ) ? sanitize_text_field( wp_unslash( $_POST['test_password'] ) ) : '';
33
34 $response = $this->mo_firebase_authenticate_call( $test_username, $test_password );
35 $response = json_decode( $response, true );
36
37 if ( isset( $response['error'] ) ) {
38 $fb_error = $response['error']['message'];
39 if ( 'INVALID_PASSWORD' === $fb_error ) {
40 $fb_error = 'The password is invalid or the user does not have a password.';
41 } elseif ( 'EMAIL_NOT_FOUND' === $fb_error ) {
42 $fb_error = 'There is no user record corresponding to this identifier. The user may have been deleted.';
43 } elseif ( 'INVALID_EMAIL' === $fb_error ) {
44 $fb_error = 'The email address is badly formatted.';
45 }
46 echo '<div style="font-family:Calibri;padding: 0 30%;">';
47 echo '<h1 style="color:#d9534f;text-align:center;">test failed</h1>';
48 echo '<h4 style="text-align:center;"><b>ERROR :</b>' . esc_attr( $fb_error ) . '</h4>';
49 echo '</div>';
50 echo '<div style="padding: 10px;"></div><div style="position:absolute;padding:0 46%;"><input style="padding:1%;width:100px;height:30px;background: #0091CD none repeat scroll 0% 0%;cursor: pointer;font-size:15px;border-width: 1px;border-style: solid;border-radius: 3px;white-space: nowrap;box-sizing: border-box;border-color: #0073AA;box-shadow: 0px 1px 0px rgba(120, 200, 230, 0.6) inset;color: #FFF;"type="button" value="Close" onClick="self.close();"></div>';
51 exit();
52 } else {
53 $id_token = $response['idToken'];
54 $payload = $this->decode_jwt( $id_token );
55 echo '<div style="font-family:Calibri;margin: auto;padding:5%;">';
56 echo '<h1 style="color:#00C851;text-align:center;">Test Successful !</h1>';
57 echo '<style>table{border-collapse:collapse;}th {background-color: #eee; text-align: center; padding: 8px; border-width:1px; border-style:solid; border-color:#212121;}tr:nth-child(odd) {background-color: #f2f2f2;} td{padding:8px;border-width:1px; border-style:solid; border-color:#212121;}</style>';
58 echo '<h3 style="text-align:center;">Test Configuration</h3><table style="margin: auto;"><tr><th>Attribute Name</th><th>Attribute Value</th></tr>';
59 $this->testattrmappingconfig( '', $payload );
60 echo '</table></div>';
61 echo '<div style="margin: auto;position:absolute;padding:0 40%;"><input style="margin: auto;position:absolute; padding:8px;width:12%;background: #0091CD none repeat scroll 0% 0%;cursor: pointer;font-size:15px;border-width: 1px;border-style: solid;border-radius: 3px;white-space: nowrap;box-sizing: border-box;border-color: #0073AA;box-shadow: 0px 1px 0px rgba(120, 200, 230, 0.6) inset;color: #FFF;"type="button" value="Done" onClick="self.close();"></div>';
62 exit();
63 }
64 }
65 }
66 /**
67 * Processing test configuration
68 *
69 * @param string $nestedprefix .
70 * @param array $payload .
71 */
72 public function testattrmappingconfig( $nestedprefix, $payload ) {
73 foreach ( $payload as $key => $value ) {
74 if ( is_array( $value ) || is_object( $value ) ) {
75 if ( ! empty( $nestedprefix ) ) {
76 $nestedprefix .= '.';
77 }
78 $this->testattrmappingconfig( $nestedprefix . $key, $value );
79 } else {
80 echo '<tr><td>';
81 if ( ! empty( $nestedprefix ) ) {
82 echo esc_attr( $nestedprefix ) . '.';
83 }
84 echo esc_attr( $key ) . '</td><td>' . esc_attr( $value ) . '</td></tr>';
85 }
86 }
87 }
88 /**
89 * Decode JWT token.
90 *
91 * @param string $jwt_token firebase ID token.
92 */
93 public function decode_jwt( $jwt_token ) {
94 $flag = 0;
95 $pieces = explode( '.', $jwt_token );
96 $jwt_data = $pieces[0] . '.' . $pieces[1];
97 $jwt_signature = str_replace( array( '-', '_' ), array( '+', '/' ), $pieces[2] );
98 $jwt_signature = base64_decode( $jwt_signature ); //phpcs:ignore -- ignoring DiscouragedPHPFunctions warning as this line of code is used for decoding JWT signature part.
99 $jwt_header = json_decode( base64_decode( str_replace( array( '-', '_' ), array( '+', '/' ), $pieces[0] ) ), true ); //phpcs:ignore -- ignoring DiscouragedPHPFunctions warning as this line of code is used for decoding JWT header part.
100
101 $alg = $jwt_header['alg'];
102 $kid = $jwt_header['kid'];
103
104 if ( strpos( $alg, 'RS' ) !== false ) {
105 $algorithm = 'RSA';
106 $sha = explode( 'RS', $alg )[1];
107 }
108
109 $jwt_raw_certificate = $this->mo_firebase_auth_get_cert_from_kid( $kid );
110
111 $public_key = '';
112 $parts = explode( '-----', $jwt_raw_certificate );
113
114 if ( preg_match( '/\r\n|\r|\n/', $parts[2] ) ) {
115 $public_key = $jwt_raw_certificate;
116 } else {
117 $encoding = '-----' . $parts[1] . "-----\n";
118 $offset = 0;
119 $segment = substr( $parts[2], $offset, 64 );
120 while ( $segment ) {
121 $encoding .= $segment . "\n";
122 $offset += 64;
123 $segment = substr( $parts[2], $offset, 64 );
124 }
125 $encoding .= '-----' . $parts[3] . "-----\n";
126 $public_key = $encoding;
127 }
128
129 switch ( $sha ) {
130 case '256':
131 $verified = openssl_verify( $jwt_data, $jwt_signature, $public_key, OPENSSL_ALGO_SHA256 );
132 break;
133 case '384':
134 $verified = openssl_verify( $jwt_data, $jwt_signature, $public_key, OPENSSL_ALGO_SHA384 );
135 break;
136 case '512':
137 $verified = openssl_verify( $jwt_data, $jwt_signature, $public_key, OPENSSL_ALGO_SHA512 );
138 break;
139 default:
140 $verified = false;
141 break;
142 }
143
144 if ( ! $verified ) {
145 echo 'Invalid Token';
146 exit();
147 }
148
149 $jwt_payload = json_decode( base64_decode( $pieces[1] ), true ); //phpcs:ignore -- ignoring DiscouragedPHPFunctions warning as this line of code is used for decoding JWT payload part.
150
151 if ( empty( $jwt_payload['exp'] ) || time() >= (int) $jwt_payload['exp'] ) {
152 echo 'Token expired';
153 exit();
154 }
155
156 $expected_project_id = get_option( 'mo_firebase_auth_project_id' );
157 if ( $expected_project_id && ( empty( $jwt_payload['aud'] ) || $jwt_payload['aud'] !== $expected_project_id ) ) {
158 echo 'Invalid token audience';
159 exit();
160 }
161
162 return $jwt_payload;
163
164 }
165
166 /**
167 * Processing Firebase JWT
168 *
169 * @param mixed $kid kid.
170 *
171 * @return mixed jwt cert
172 */
173 public function mo_firebase_auth_get_cert_from_kid( $kid ) {
174 $flag = $this->mo_firebase_auth_get_kid( $kid );
175 if ( 0 === $flag ) {
176 $firebaselogin = new Miniorange_Firebase_Authentication();
177 $firebaselogin->mo_firebase_auth_store_certificates();
178 $flag = $this->mo_firebase_auth_get_kid( $kid );
179 }
180 if ( 0 !== $flag ) {
181 if ( 1 === $flag ) {
182 $jwt_raw_certificate = get_option( 'mo_firebase_auth_cert1' );
183 } elseif ( 2 === $flag ) {
184 $jwt_raw_certificate = get_option( 'mo_firebase_auth_cert2' );
185 } elseif ( 3 === $flag ) {
186 $jwt_raw_certificate = get_option( 'mo_firebase_auth_cert3' );
187 }
188 } else {
189 echo 'Please provide a valid certificate. Contact your administrator.';
190 exit;
191 }
192 return $jwt_raw_certificate;
193 }
194
195 /**
196 * Function included in JWT processing
197 *
198 * @param mixed $kid kid.
199 *
200 * @return int
201 */
202 public function mo_firebase_auth_get_kid( $kid ) {
203 $flag = 0;
204 $kid_stored = get_option( 'mo_firebase_auth_kid1' );
205 if ( $kid_stored !== $kid ) {
206 $flag = 2;
207 $kid_stored = get_option( 'mo_firebase_auth_kid2' );
208 if ( $kid_stored !== $kid ) {
209 $flag = 3;
210 $kid_stored = get_option( 'mo_firebase_auth_kid3' );
211 if ( $kid_stored !== $kid ) {
212 $flag = 0;
213 }
214 }
215 } else {
216 $flag = 1;
217 }
218 return $flag;
219 }
220
221 /**
222 * Check the user and set the session or return WP error
223 *
224 * @param mixed $fb_idtoken firebase Id token.
225 *
226 * @return object WP_User/WP_Error .
227 */
228 public function mo_fb_login_user( $fb_idtoken ) {
229
230 $payload = $this->decode_jwt( $fb_idtoken );
231
232 $user = $this->get_user( $payload );
233 if ( is_wp_error( $user ) ) {
234 return $user;
235 } else {
236 $user_id = $user->ID;
237 wp_set_auth_cookie( $user_id, true );
238 wp_safe_redirect( home_url() );
239 exit;
240 }
241
242 }
243
244 /**
245 * Get the user object from WordPress
246 *
247 * @param array $jwt_payload Firebase Id token payload.
248 */
249 public function get_user( $jwt_payload ) {
250 if ( isset( $jwt_payload['email'] ) ) {
251 $email = $jwt_payload['email'];
252 $firebase_uid = isset( $jwt_payload['sub'] ) ? $jwt_payload['sub'] : ( isset( $jwt_payload['user_id'] ) ? $jwt_payload['user_id'] : '' );
253 $user = null;
254
255 if ( $firebase_uid ) {
256 $bound_users = get_users(
257 array(
258 'meta_key' => 'mo_firebase_user_uid',
259 'meta_value' => $firebase_uid,
260 'number' => 1,
261 )
262 );
263 if ( ! empty( $bound_users ) ) {
264 $user = $bound_users[0];
265 }
266 }
267
268 if ( ! $user ) {
269 $user = get_user_by( 'email', $email );
270 if ( ! $user ) {
271 $user = get_user_by( 'login', $email );
272 }
273 }
274
275 if ( get_option( 'mo_firebase_email_verified_login' ) && empty( $jwt_payload['email_verified'] ) ) {
276 return new WP_Error(
277 'firebase_email_not_verified',
278 __( 'Your email is not verified. Please verify your email before logging in.', 'firebase-authentication' )
279 );
280 }
281
282 if ( $user ) {
283 if ( $firebase_uid ) {
284 update_user_meta( $user->ID, 'mo_firebase_user_uid', $firebase_uid );
285 }
286 return $user;
287 }
288
289 $user_password = wp_generate_password( 10, false );
290
291 $userdata = array(
292 'user_login' => $email,
293 'user_pass' => $user_password,
294 'user_email' => $email,
295 );
296
297 $user_id = wp_insert_user( $userdata );
298
299 if ( ! is_wp_error( $user_id ) ) {
300 update_user_meta( $user_id, 'mo_firebase_user_dn', false );
301 if ( $firebase_uid ) {
302 update_user_meta( $user_id, 'mo_firebase_user_uid', $firebase_uid );
303 }
304 }
305
306 return get_user_by( 'email', $email );
307 }
308 }
309 /**
310 * Function to call Firebase email password API
311 *
312 * @param string $url .
313 * @param string $headers .
314 * @param string $body .
315 */
316 public function mo_fb_post_api( $url, $headers, $body ) {
317
318 $args = array(
319 'method' => 'POST',
320 'body' => $body,
321 'timeout' => '5',
322 'redirection' => '5',
323 'httpversion' => '1.0',
324 'blocking' => true,
325 'headers' => $headers,
326
327 );
328
329 $response = wp_remote_post( $url, $args );
330
331 if ( is_wp_error( $response ) ) {
332 $error_message = $response->get_error_message();
333 echo 'Something went wrong: ' . esc_attr( $error_message );
334 exit();
335 }
336
337 return wp_remote_retrieve_body( $response );
338 }
339
340 /**
341 * Function to call Firebase email password API
342 *
343 * @param string $email .
344 * @param string $password .
345 */
346 public function mo_firebase_authenticate_call( $email, $password ) {
347
348 $api_key = get_option( 'mo_firebase_auth_api_key' );
349
350 $url = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=' . $api_key;
351
352 $params = array(
353 'email' => $email,
354 'password' => $password,
355 'returnSecureToken' => true,
356 );
357
358 $body = wp_json_encode( $params );
359
360 $headers = array(
361 'Content-Type' => 'application/json',
362 'Content-Length' => strlen( $body ),
363 );
364
365 $response = $this->mo_fb_post_api( $url, $headers, $body );
366
367 return $response;
368 }
369
370 }
371
372 $mo_firebase_config_obj = new Mo_Firebase_Config();
373