| @@ -4,55 +4,49 @@ | ||
| 4 | 4 | die('Hacking Attempt!'); |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | 7 | include_once dirname(__FILE__, 2) . '/lib/hybridauth/autoload.php'; |
| 8 | +include_once __DIR__ .'/social-base.php'; | |
| 8 | 9 | |
| 9 | 10 | use Hybridauth\Exception\Exception; |
| 10 | 11 | use Hybridauth\Hybridauth; |
| 11 | 12 | use Hybridauth\HttpClient; |
| 12 | -use Hybridauth\Storage\Session; | |
| 13 | +use Hybridauth\Storage\Transient; | |
| 13 | 14 | |
| 14 | -class Loginizer_Social_Login{ | |
| 15 | +class Loginizer_Social_Login extends Loginizer_Social_Base{ | |
| 15 | 16 | |
| 16 | - public static $error = []; | |
| 17 | - public static $test = false; | |
| 18 | - public static $ref = ''; | |
| 19 | - public static $interim_login = ''; | |
| 20 | - public static $provider = ''; | |
| 21 | - public static $storage; | |
| 22 | - | |
| 23 | 17 | // Process all the requests from here. |
| 24 | 18 | static function login_init(){ |
| 25 | 19 | global $loginizer; |
| 26 | 20 | |
| 27 | - self::$storage = new Session(); | |
| 21 | + try { | |
| 22 | + self::$storage = new Transient(); | |
| 28 | 23 | |
| 29 | - // Security check here. | |
| 30 | - $lz_social_nonce = ''; | |
| 31 | - if(!empty($_GET['social_security'])){ | |
| 32 | - $lz_social_nonce = sanitize_text_field(wp_unslash($_GET['social_security'])); | |
| 33 | - } elseif(!empty(self::$storage) && !empty(self::$storage->get('social_security'))){ | |
| 34 | - $lz_social_nonce = sanitize_text_field(self::$storage->get('social_security')); | |
| 35 | - } | |
| 24 | + // Security check here. | |
| 25 | + $lz_social_nonce = ''; | |
| 26 | + if(!empty($_GET['social_security'])){ | |
| 27 | + $lz_social_nonce = sanitize_text_field(wp_unslash($_GET['social_security'])); | |
| 28 | + } elseif(!empty(self::$storage) && !empty(self::$storage->get('social_security'))){ | |
| 29 | + $lz_social_nonce = sanitize_text_field(self::$storage->get('social_security')); | |
| 30 | + } | |
| 36 | 31 | |
| 37 | - if(!wp_verify_nonce($lz_social_nonce, 'loginizer_social_check')){ | |
| 38 | - self::$error['security-check'] = __('Security check failed when trying to login', 'loginizer'); | |
| 39 | - self::trigger_error(); | |
| 40 | - return; | |
| 41 | - } | |
| 32 | + if(!wp_verify_nonce($lz_social_nonce, 'loginizer_social_check')){ | |
| 33 | + self::$error['security-check'] = __('Security check failed when trying to login', 'loginizer'); | |
| 34 | + self::trigger_error(); | |
| 35 | + return; | |
| 36 | + } | |
| 42 | 37 | |
| 43 | - $providers = self::build_provider_arr(); | |
| 38 | + $providers = self::build_provider_arr(); | |
| 44 | 39 | |
| 45 | - if(empty($providers)){ | |
| 46 | - self::$error['login_error'] = __('No Provider is configured, please contact the admin about this issue', 'loginizer'); | |
| 47 | - self::trigger_error(); | |
| 48 | - return; | |
| 49 | - } | |
| 40 | + if(empty($providers)){ | |
| 41 | + self::$error['login_error'] = __('No Provider is configured, please contact the admin about this issue', 'loginizer'); | |
| 42 | + self::trigger_error(); | |
| 43 | + return; | |
| 44 | + } | |
| 50 | 45 | |
| 51 | - $callback_query = []; | |
| 52 | - $callback_query['lz_social_provider'] = lz_optget('lz_social_provider'); | |
| 46 | + $callback_query = []; | |
| 47 | + $callback_query['lz_social_provider'] = lz_optget('lz_social_provider'); | |
| 53 | 48 | |
| 54 | - try { | |
| 55 | 49 | $config = [ |
| 56 | 50 | // Location where to redirect users once they authenticate with a provider |
| 57 | 51 | 'callback' => wp_login_url().'?'.http_build_query($callback_query), |
| 58 | 52 | |
| @@ -59,9 +53,9 @@ | ||
| 59 | 53 | // Providers specifics |
| 60 | 54 | 'providers' => $providers |
| 61 | 55 | ]; |
| 62 | 56 | |
| 63 | - $hybridauth = new Hybridauth($config); | |
| 57 | + $hybridauth = new Hybridauth($config, null, self::$storage); | |
| 64 | 58 | |
| 65 | 59 | //Step 1: Here we will be redirected to the App Auth page |
| 66 | 60 | if(!empty($_GET['lz_social_provider'])){ |
| 67 | 61 | if(is_array($hybridauth->getProviders()) && in_array($_GET['lz_social_provider'], $hybridauth->getProviders())) { |
| @@ -72,9 +66,9 @@ | ||
| 72 | 66 | self::$storage->set('test', true); |
| 73 | 67 | } |
| 74 | 68 | |
| 75 | 69 | self::$storage->set('social_security', wp_create_nonce('loginizer_social_check')); |
| 76 | - | |
| 70 | + | |
| 77 | 71 | if(!empty($_REQUEST['ref']) && wp_http_validate_url(sanitize_url(wp_unslash($_REQUEST['ref'])))){ |
| 78 | 72 | self::$storage->set('ref', rawurlencode(sanitize_url(wp_unslash($_REQUEST['ref'])))); |
| 79 | 73 | } |
| 80 | 74 | |
| @@ -137,9 +131,9 @@ | ||
| 137 | 131 | 'identifier' => $userProfile->identifier, |
| 138 | 132 | 'email' => $userProfile->email, |
| 139 | 133 | 'first_name' => $userProfile->firstName, |
| 140 | 134 | 'last_name' => $userProfile->lastName, |
| 141 | - 'photoURL' => strtok($userProfile->photoURL, '?'), | |
| 135 | + 'photoURL' => !empty($userProfile->photoURL) ? strtok($userProfile->photoURL, '?') : '', | |
| 142 | 136 | ]; |
| 143 | 137 | |
| 144 | 138 | $adapter->disconnect(); |
| 145 | 139 | |
| @@ -191,9 +185,9 @@ | ||
| 191 | 185 | self::close_tab(); |
| 192 | 186 | } |
| 193 | 187 | |
| 194 | 188 | }catch(\Exception $e){ |
| 195 | - @error_log('Loginizer Logs(Social): '. esc_html($e->getMessage())); | |
| 189 | + @error_log('Loginizer Log(Social): '. esc_html($e->getMessage())); | |
| 196 | 190 | self::$error['login_error'] = __('Oops, we ran into an issue! ', 'loginizer') . $e->getMessage(); |
| 197 | 191 | self::trigger_error(); |
| 198 | 192 | //wp_safe_redirect(wp_login_url()); |
| 199 | 193 | return; |
| @@ -199,94 +193,9 @@ | ||
| 199 | 193 | return; |
| 200 | 194 | } |
| 201 | 195 | } |
| 202 | 196 | |
| 203 | - private static function login_user($user, $username = '', $password = ''){ | |
| 204 | - | |
| 205 | - if(isset($user) && is_object($user) && property_exists($user, 'ID') && empty(self::$test)){ | |
| 206 | - clean_user_cache(get_current_user_id()); | |
| 207 | - clean_user_cache($user->ID); | |
| 208 | - wp_clear_auth_cookie(); | |
| 209 | - wp_set_current_user($user->ID, $user->user_login); | |
| 210 | - wp_set_auth_cookie($user->ID, true, is_ssl()); | |
| 211 | - do_action('wp_login', $user->user_login, $user); | |
| 212 | - update_user_caches($user); | |
| 213 | - | |
| 214 | - return true; | |
| 215 | - } | |
| 216 | - } | |
| 217 | - | |
| 218 | 197 | /** |
| 219 | - * Creates a User account | |
| 220 | - * | |
| 221 | - * @param mixed[] $data Data we get from the Social App | |
| 222 | - * @return void | |
| 223 | - */ | |
| 224 | - static function register_account($data){ | |
| 225 | - global $loginizer; | |
| 226 | - | |
| 227 | - $username = $data['first_name'] . $data['last_name']; | |
| 228 | - | |
| 229 | - if(empty($username)){ | |
| 230 | - $parsed_email = explode('@', $data['email']); | |
| 231 | - | |
| 232 | - if(!empty($parsed_email[0])){ | |
| 233 | - $username = preg_replace('/[^A-Za-z0-9\-]/', '', $parsed_email[0]); | |
| 234 | - } | |
| 235 | - } | |
| 236 | - | |
| 237 | - $username = str_replace(' ', '', strtolower($username)); | |
| 238 | - $username = sanitize_user($username, true); | |
| 239 | - | |
| 240 | - $i = 1; | |
| 241 | - while(username_exists($username)){ | |
| 242 | - $username .= $i; | |
| 243 | - $i++; | |
| 244 | - } | |
| 245 | - | |
| 246 | - $password = wp_generate_password(12); | |
| 247 | - $userdata = [ | |
| 248 | - 'user_login' => sanitize_text_field($username), | |
| 249 | - 'user_pass' => $password, | |
| 250 | - 'user_email' => sanitize_email($data['email']), | |
| 251 | - 'role' => (!empty($loginizer['social_settings']['general']['default_role']) ? sanitize_text_field($loginizer['social_settings']['general']['default_role']) : 'subscriber'), | |
| 252 | - 'show_admin_bar_front' => (!empty($loginizer['social_settings']['general']['hide_admin_bar']) ? false : true), | |
| 253 | - ]; | |
| 254 | - | |
| 255 | - $user_id = wp_insert_user($userdata); | |
| 256 | - | |
| 257 | - // TODO: Handle Error here. | |
| 258 | - if(is_wp_error($user_id)){ | |
| 259 | - self::$error['registration_failed'] = __('Something went wrong while creating the user', 'loginizer'). $user_id->get_error_message(); | |
| 260 | - return; | |
| 261 | - } | |
| 262 | - | |
| 263 | - if(empty($user_id)){ | |
| 264 | - self::$error['registration_failed'] = __('Unable to register your account, try again later!', 'loginizer'); | |
| 265 | - self::close_tab(); | |
| 266 | - return; | |
| 267 | - } | |
| 268 | - | |
| 269 | - update_user_option($user_id, 'default_password_nag', true, true); // This will show alert to user to change the password. | |
| 270 | - $user = get_user_by('ID', $user_id); | |
| 271 | - | |
| 272 | - // Save avatar if possible. | |
| 273 | - $tried_to_download = get_user_meta($user->ID, 'loginizer_avatar_download', true); | |
| 274 | - if(!empty($data['photoURL']) && !empty($loginizer['social_settings']['general']['save_avatar']) && empty($tried_to_download)){ | |
| 275 | - self::save_avatar($data['photoURL'], $user->ID); | |
| 276 | - } | |
| 277 | - | |
| 278 | - // Logging In the new user. | |
| 279 | - self::login_user($user); | |
| 280 | - | |
| 281 | - // Closing the tab and redirecting to the admin. | |
| 282 | - $redirect_to = admin_url(); | |
| 283 | - | |
| 284 | - self::close_tab(); | |
| 285 | - | |
| 286 | - } | |
| 287 | - | |
| 288 | - /** | |
| 289 | 198 | * Creates an array of Config which is valid for HybridAuth using the setting of the provider. |
| 290 | 199 | * |
| 291 | 200 | * @return mixed[] |
| 292 | 201 | */ |
| @@ -312,250 +221,15 @@ | ||
| 312 | 221 | 'id' => $provider['client_id'], |
| 313 | 222 | 'secret' => $provider['client_secret'] |
| 314 | 223 | ] |
| 315 | 224 | ]; |
| 225 | + | |
| 226 | + if($key == 'MicrosoftGraph' && !empty($provider['account_type']) && $provider['account_type'] != 'common'){ | |
| 227 | + $config[$config_index]['tenant'] = $provider['account_type']; | |
| 228 | + } | |
| 316 | 229 | } |
| 317 | 230 | |
| 318 | 231 | return $config; |
| 319 | - } | |
| 320 | - | |
| 321 | - /** | |
| 322 | - * Close the Tab or redirects back to the Login Page. | |
| 323 | - * | |
| 324 | - * @param string $redirect_to URL where the user should be redirected, leave empty if want to redirect to admin. | |
| 325 | - * @return void | |
| 326 | - */ | |
| 327 | - protected static function close_tab(){ | |
| 328 | - global $loginizer; | |
| 329 | - | |
| 330 | - // Check if the URL is safe to use. | |
| 331 | - if(!empty(self::$ref)){ | |
| 332 | - $redirect_to = self::handle_redirect(self::$ref); | |
| 333 | - } | |
| 334 | - | |
| 335 | - $target_window = 'same'; // If to redirect or to close the poup | |
| 336 | - $is_interim = ''; // If interim add query string as a identifier | |
| 337 | - if(self::$interim_login == 'lz'){ | |
| 338 | - $target_window = 'popup'; | |
| 339 | - $is_interim = '?interim_login=lz'; | |
| 340 | - } else if(!empty(self::$test)){ | |
| 341 | - $target_window = 'popup'; | |
| 342 | - | |
| 343 | - $redirect_to .= '&provider='.self::$provider.'&test=1'; | |
| 344 | - }else if(!empty($loginizer['social_settings']['general']['target_window'])){ | |
| 345 | - $target_window = $loginizer['social_settings']['general']['target_window']; | |
| 346 | - } | |
| 347 | - | |
| 348 | - if(empty($redirect_to) || $redirect_to == admin_url()){ | |
| 349 | - $redirect_to = admin_url($is_interim); | |
| 350 | - } | |
| 351 | - | |
| 352 | - if($target_window === 'same'){ | |
| 353 | - wp_safe_redirect($redirect_to); | |
| 354 | - die(); | |
| 355 | - } | |
| 356 | - | |
| 357 | - if(isset(self::$interim_login) && self::$interim_login === 'lz' && is_user_logged_in()){ | |
| 358 | - echo esc_html__('Login Successful', 'loginizer'); | |
| 359 | - } | |
| 360 | - | |
| 361 | - echo '<script> | |
| 362 | - window.opener.location.href="'.wp_validate_redirect(wp_sanitize_redirect($redirect_to)).'"; | |
| 363 | - window.close(); | |
| 364 | - </script>'; | |
| 365 | - | |
| 366 | - die(); | |
| 367 | - } | |
| 368 | - | |
| 369 | - // Download the avatar and returns Image ID | |
| 370 | - protected static function save_avatar($url, $user_id){ | |
| 371 | - | |
| 372 | - update_user_meta($user_id, 'loginizer_avatar_download', true); | |
| 373 | - | |
| 374 | - $tmp_file = self::download_avatar($url); | |
| 375 | - | |
| 376 | - if(is_wp_error($tmp_file) || empty($tmp_file)){ | |
| 377 | - return $tmp_file; | |
| 378 | - } | |
| 379 | - | |
| 380 | - $mime = wp_get_image_mime($tmp_file); | |
| 381 | - | |
| 382 | - $allowed_mime = [ | |
| 383 | - 'image/webp' => 'webp', | |
| 384 | - 'image/tiff' => 'tif', | |
| 385 | - 'image/gif' => 'gif', | |
| 386 | - 'image/jpeg' => 'jpg', | |
| 387 | - 'image/bmp' => 'bmp', | |
| 388 | - 'image/png' => 'png', | |
| 389 | - ]; | |
| 390 | - | |
| 391 | - if(!array_key_exists($mime, $allowed_mime)){ | |
| 392 | - error_log('Loginizer Error: ' . __('The avatar has unsupported mime type.', 'loginizer')); | |
| 393 | - return; | |
| 394 | - } | |
| 395 | - | |
| 396 | - $upload_dir = wp_upload_dir(); | |
| 397 | - $avatar_upload_dir = trailingslashit($upload_dir['basedir']) . 'lz_avatars'; | |
| 398 | - | |
| 399 | - if(!wp_mkdir_p($avatar_upload_dir)){ | |
| 400 | - error_log('Loginizer Error: ' . __('Unable to create Directory to save avatars', 'loginizer')); | |
| 401 | - return; | |
| 402 | - } | |
| 403 | - | |
| 404 | - $avatar_file = wp_hash($user_id) .'.'. $allowed_mime[$mime]; | |
| 405 | - $avatar_file = wp_unique_filename($avatar_upload_dir, $avatar_file); | |
| 406 | - $avatar_file_path = trailingslashit($avatar_upload_dir) . $avatar_file; | |
| 407 | - | |
| 408 | - $new_file = copy($tmp_file, $avatar_file_path); | |
| 409 | - unlink($tmp_file); | |
| 410 | - | |
| 411 | - if(empty($new_file)){ | |
| 412 | - error_log('Loginizer Error: ' . __('Unable to copy the avatar from the tmp file', 'loginizer')); | |
| 413 | - return; | |
| 414 | - } | |
| 415 | - | |
| 416 | - $avatar_url = $upload_dir['baseurl'] . '/lz_avatars/' . basename($avatar_file); | |
| 417 | - | |
| 418 | - $attachment = [ | |
| 419 | - 'guid' => $avatar_url, | |
| 420 | - 'post_title' => '', | |
| 421 | - 'post_content' => '', | |
| 422 | - 'post_author' => $user_id, | |
| 423 | - 'post_status' => 'private', | |
| 424 | - 'post_mime_type' => $mime, | |
| 425 | - ]; | |
| 426 | - | |
| 427 | - $attachment_id = wp_insert_attachment($attachment, $avatar_file_path); | |
| 428 | - | |
| 429 | - if(is_wp_error($attachment_id)){ | |
| 430 | - unlink($avatar_file_path); | |
| 431 | - error_log('Loginizer Error: ' . __('Unable to create an attachment of the Avatar', 'loginizer')); | |
| 432 | - return; | |
| 433 | - } | |
| 434 | - | |
| 435 | - global $wpdb, $blog_id; | |
| 436 | - | |
| 437 | - include_once(ABSPATH . 'wp-admin/includes/image.php'); | |
| 438 | - | |
| 439 | - wp_update_attachment_metadata($attachment_id, wp_generate_attachment_metadata($attachment_id, $avatar_file_path)); | |
| 440 | - | |
| 441 | - update_post_meta($attachment_id, '_wp_attachment_wp_user_avatar', $user_id); | |
| 442 | - update_user_meta($user_id, $wpdb->get_blog_prefix($blog_id) . 'lz_avatar', $attachment_id); | |
| 443 | - | |
| 444 | - } | |
| 445 | - | |
| 446 | - private static function download_avatar($url){ | |
| 447 | - | |
| 448 | - if(empty($url)){ | |
| 449 | - error_log('Loginizer Error: ' . __('The URL provided to download avatar is empty', 'loginizer')); | |
| 450 | - return; | |
| 451 | - } | |
| 452 | - | |
| 453 | - $tmp_file = uniqid(); | |
| 454 | - | |
| 455 | - if(empty($tmp_file)){ | |
| 456 | - error_log('Loginizer Error: ' . __('Unable to create a tmp file!', 'loginizer')); | |
| 457 | - return; | |
| 458 | - } | |
| 459 | - | |
| 460 | - $response = wp_remote_get($url, [ | |
| 461 | - 'timeout' => 30, | |
| 462 | - 'stream' => true, | |
| 463 | - 'filename' => $tmp_file, | |
| 464 | - ]); | |
| 465 | - | |
| 466 | - if(is_wp_error($response)){ | |
| 467 | - unlink($tmp_file); | |
| 468 | - error_log('Loginizer Error: ' . __('Download of the avatar failed!', 'loginizer')); | |
| 469 | - return; | |
| 470 | - } | |
| 471 | - | |
| 472 | - $code = wp_remote_retrieve_response_code($response); | |
| 473 | - | |
| 474 | - if($code != 200){ | |
| 475 | - unlink($tmp_file); | |
| 476 | - error_log('Loginizer Error: ' . sprintf(__('Download of the avatar failed with error code %s!', 'loginizer'), esc_html($code))); | |
| 477 | - return; | |
| 478 | - } | |
| 479 | - | |
| 480 | - $content_md5 = wp_remote_retrieve_header($response, 'content-md5'); | |
| 481 | - if(!empty($content_md5)){ | |
| 482 | - if(!function_exists('verify_file_md5')){ | |
| 483 | - include_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 484 | - } | |
| 485 | - | |
| 486 | - $md5_check = verify_file_md5($tmp_file, $content_md5); | |
| 487 | - if(is_wp_error($md5_check)){ | |
| 488 | - unlink($tmpfname); | |
| 489 | - return $md5_check; | |
| 490 | - } | |
| 491 | - } | |
| 492 | - | |
| 493 | - return $tmp_file; | |
| 494 | - } | |
| 495 | - | |
| 496 | - protected static function handle_redirect($url){ | |
| 497 | - | |
| 498 | - $redirect = ''; | |
| 499 | - if(empty($url)){ | |
| 500 | - return $redirect; | |
| 501 | - } | |
| 502 | - | |
| 503 | - $url = rawurldecode($url); | |
| 504 | - $parsed_url = parse_url($url); | |
| 505 | - | |
| 506 | - // If we have something in redirect to, then redirect to that page | |
| 507 | - if(!empty($parsed_url['query'])){ | |
| 508 | - preg_match('/(redirect_to|redirect)=([^&]*)/', $parsed_url['query'], $redirect_url); | |
| 509 | - | |
| 510 | - if(!empty($redirect_url[2])){ | |
| 511 | - return rawurldecode($redirect_url[2]); | |
| 512 | - } | |
| 513 | - } | |
| 514 | - | |
| 515 | - // Reloading the page wont show the admin page so we need to redirect it to the admin page. | |
| 516 | - if($parsed_url['scheme'].'://'.$parsed_url['host'] . $parsed_url['path'] == wp_login_url()){ | |
| 517 | - return $redirect; | |
| 518 | - } | |
| 519 | - | |
| 520 | - if(strpos(wp_login_url(), $parsed_url['path']) !== FALSE){ | |
| 521 | - return $redirect; | |
| 522 | - } | |
| 523 | - | |
| 524 | - // If none of the above happens then we will just make the page reload. | |
| 525 | - return $url; | |
| 526 | - } | |
| 527 | - | |
| 528 | - static function trigger_error(){ | |
| 529 | - if(empty(self::$error)){ | |
| 530 | - return; | |
| 531 | - } | |
| 532 | - | |
| 533 | - // If we are testing we can just die, | |
| 534 | - // becuase we don't want the user to be redirected anywhere | |
| 535 | - if(!empty(self::$test) || (!empty(self::$storage) && self::$storage->get('test'))){ | |
| 536 | - wp_die(wp_kses_post(current(self::$error))); | |
| 537 | - } | |
| 538 | - | |
| 539 | - do_action('wp_login_failed', ''); | |
| 540 | - | |
| 541 | - self::error_state(); | |
| 542 | - self::close_tab(); // This will redirect to the appropriate page. | |
| 543 | - } | |
| 544 | - | |
| 545 | - // Stores the errors to be used once redirected. | |
| 546 | - static function error_state(){ | |
| 547 | - global $loginizer; | |
| 548 | - | |
| 549 | - $data = [ | |
| 550 | - 'errors' => self::$error, | |
| 551 | - 'retries_left' => $loginizer['retries_left'] | |
| 552 | - ]; | |
| 553 | - | |
| 554 | - $identifier = uniqid('lz_social', true); | |
| 555 | - set_site_transient($identifier, $data, 300); | |
| 556 | - | |
| 557 | - setcookie('lz_social_error', $identifier, time() + 300, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true); | |
| 558 | 232 | } |
| 559 | 233 | } |
| 560 | 234 | |
| 561 | 235 | Loginizer_Social_Login::login_init(); |