jfb_process_login

The WP-FB-AutoConnect jfb process login function.

Description

jfb_process_login(); 

Usage

  1. if ( !function_exists( 'jfb_process_login' ) ) { 
  2. require_once ABSPATH . PLUGINDIR . 'wp-fb-autoconnect/_process_login.php'; 
  3.  
  4.  
  5. // NOTICE! Understand what this does before running. 
  6. $result = jfb_process_login(); 
  7.  

Defined (1)

The function is defined in the following location(s).

/_process_login.php  
  1. function jfb_process_login() 
  2. //If this pageload isn't supposed to be handing a login, just stop here. 
  3. global $jfb_nonce_name; 
  4. if( !isset($_POST[$jfb_nonce_name]) ) return; 
  5.  
  6. //Start logging 
  7. global $jfb_log, $jfb_version, $opt_jfb_app_id, $jfb_homepage, $jfb_apiver; 
  8. $browser = jfb_get_browser(); 
  9. $jfb_log = "Starting login process (IP: " . $_SERVER['REMOTE_ADDR'] . ", User: " . $_POST['fbuid'] . ", App: " . get_option($opt_jfb_app_id) . ", Plugin: $jfb_version, WP: " . $GLOBALS['wp_version'] . ", API: " . $jfb_apiver . ", Browser: " . $browser['shortname'] . " " . $browser['version'] . " for " . $browser['platform'] . ")\n"; 
  10.  
  11. //Run one hook before ANYTHING happens. 
  12. $jfb_log .= "WP: Running action wpfb_prelogin\n"; 
  13. do_action('wpfb_prelogin'); 
  14.  
  15. //Check the nonce to make sure this was a valid login attempt (unless the user has disabled nonce checking) 
  16. global $opt_jfb_disablenonce, $jfb_nonce_name; 
  17. if( !get_option($opt_jfb_disablenonce) ) 
  18. if( wp_verify_nonce ($_REQUEST[$jfb_nonce_name], $jfb_nonce_name) != 1 ) 
  19. //If there's already a user logged in, tell the user and give them a link back to where they were. 
  20. $currUser = wp_get_current_user();  
  21. if( $currUser->ID ) 
  22. $msg = sprintf(__("User '%s' has already logged in via another browser session.", 'wp-fb-autoconnect'), $currUser->user_login) . "\n"; 
  23. $jfb_log .= $msg; 
  24. j_mail("FB Double-Login: " . $currUser->user_login . " -> " . get_bloginfo('name')); 
  25. die($msg . "<br /><br /><a href=\"".$_POST['redirectTo']."\">" . __("Continue", 'wp-fb-autoconnect')."</a>"); 
  26.  
  27. j_die("Nonce check failed, login aborted.\n<br/><br/>\n" . __("Thiserroris usually due to your browser's privacy settings or a server-side caching plugin. If you get thiserroron multiple browsers, please contact the site administrator.", 'wp-fb-autoconnect')); 
  28. $jfb_log .= "WP: nonce check passed\n"; 
  29. else 
  30. $jfb_log .= "WP: nonce check DISABLED\n"; 
  31.  
  32. //Get the redirect URL 
  33. global $redirectTo; 
  34. if( !isset($_POST['redirectTo']) || !$_POST['redirectTo'] ) 
  35. j_die("Error: Missing redirect URL"); 
  36. $redirectTo = $_POST['redirectTo']; 
  37. $jfb_log .= "WP: Found redirect URL ($redirectTo)\n"; 
  38.  
  39. //Get the Facebook access token 
  40. if( !isset($_POST['access_token']) || !$_POST['access_token'] ) 
  41. global $opt_jfb_email_logs_missingpost; 
  42. j_die("Error: Missing Facebook access token.\n<br/><br/>\n" . sprintf(__("If you're receiving this notice via e-mail as a site administrator, it's nearly always safe to ignore (these errors are due to spambots automatically hitting your site). If you're seeing this as a real person attempting to login, please report it to the plugin author at %s.", 'wp-fb-autoconnect'), $jfb_homepage), !get_option($opt_jfb_email_logs_missingpost)); 
  43. $access_token = esc_html($_POST['access_token']); 
  44. $jfb_log .= "FB: Found access token (" . substr($access_token, 0, 30) . "...)\n";  
  45.  
  46. //Get the basic user info and make sure the access_token is valid  
  47. $jfb_log .= "FB: Initiating Facebook connection...\n"; 
  48. $fbuser = jfb_api_get("https://graph.facebook.com/$jfb_apiver/me?access_token=$access_token&fields=id, name, first_name, last_name, email, link"); 
  49. if( isset($fbuser[error]) ) j_die("Error: Failed to get the Facebook user session (" . $fbuser[error]['message'] . ")"); 
  50. if( !isset($fbuser['id']) || !$fbuser['id']) j_die("Error: Failed to get the Facebook user id (fbuser: " . print_r($fbuser, true) . ")"); 
  51. $fb_uid = $fbuser['id']; 
  52. do_action('wpfb_session_established', array('FB_ID' => $fb_uid, 'access_token'=>$access_token) ); 
  53. $jfb_log .= "FB: Connected to session (uid $fb_uid)\n"; 
  54.  
  55. //Get the profile URL & avatars. TODO: I should try to combine these into fewer queries, for better efficiency. 
  56. //NOTE: Up to 08/11/2014, I was fetching both avatars in one fql call: 
  57. //jfb_api_get("https://graph.facebook.com/fql?q=".urlencode("SELECT pic_square, pic_big FROM user WHERE uid=$fb_uid")."&access_token=$access_token"); 
  58. //However, Graph API 2.1 removed fql - so I now have fetch them separately :( 
  59. $fbuser['profile_url'] = $fbuser['link']; 
  60. $pic = jfb_api_get("https://graph.facebook.com/$jfb_apiver/me/picture?".apply_filters("wpfb_avatar_size", "type=square", "thumb")."&redirect=false&access_token=$access_token"); 
  61. $fbuser['pic_square'] = $pic['data']['url'];  
  62. $pic = jfb_api_get("https://graph.facebook.com/$jfb_apiver/me/picture?".apply_filters("wpfb_avatar_size", "type=large", "full")."&redirect=false&access_token=$access_token"); 
  63. $fbuser['pic_big'] = $pic['data']['url']; 
  64. $jfb_log .= "FB: Got user info (".$fbuser['name'].")\n"; 
  65.  
  66. //See if we were given permission to access the user's email 
  67. //This isn't required, and will only matter if it's a new user without an existing WP account 
  68. //(since we'll auto-register an account for them, using the contact_email we get from Facebook - if we can...) 
  69. $userRevealedEmail = false; 
  70. if( isset($fbuser['email']) && strlen($fbuser['email']) != 0 && strpos($fbuser['email'], 'proxymail.facebook.com') === FALSE ) 
  71. $jfb_log .= "FB: Email privilege granted (" .$fbuser['email'] . ")\n"; 
  72. $userRevealedEmail = true; 
  73. else if( isset($fbuser['email']) && strlen($fbuser['email']) != 0 ) 
  74. $jfb_log .= "FB: Email privilege granted, but only for an anonymous proxy address (" . $fbuser['email'] . ")\n"; 
  75. else 
  76. global $jfb_default_email; 
  77. $jfb_log .= "FB: Email priviledge denied.\n"; 
  78. $fbuser['email'] = "FB_" . $fb_uid . $jfb_default_email; 
  79. }  
  80.  
  81.  
  82. //Run a hook so users can`examine this Facebook user *before* letting them login. You might use this 
  83. //to limit logins based on friendship status - if someone isn't your friend, you could redirect them 
  84. //to anerrorpage (and terminate this script). 
  85. $jfb_log .= "WP: Running action wpfb_connect\n"; 
  86. do_action('wpfb_connect', array('FB_ID' => $fb_uid, 'access_token'=>$access_token) ); 
  87.  
  88.  
  89. //Examine all existing WP users to see if any of them match this Facebook user.  
  90. //The base query for getting the users comes from get_users_from_blog(), to which I add a subquery 
  91. //that limits results only to users who also have the appropriate facebook usermeta. 
  92. global $wp_users, $jfb_uid_meta_name; 
  93. if(!isset($wp_users)) 
  94. global $wpdb, $blog_id; 
  95. if ( empty($id) ) $id = (int) $blog_id; 
  96. $blog_prefix = $wpdb->get_blog_prefix($id); 
  97. $sql = "SELECT user_id, user_id AS ID, user_login, display_name, user_email, meta_value ". 
  98. "FROM $wpdb->users, $wpdb->usermeta ". 
  99. "WHERE {$wpdb->users}.ID = {$wpdb->usermeta}.user_id AND meta_key = '{$blog_prefix}capabilities' ". 
  100. "AND {$wpdb->users}.ID IN (SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = '$jfb_uid_meta_name' AND meta_value = '$fb_uid')"; 
  101. $sql = apply_filters('wpfb_candidate_users_query', $sql, $fb_uid ); 
  102. $wp_users = $wpdb->get_results( $sql ); 
  103.  
  104. //Although $wp_users should only contain the one matching user (or be empty), this "loop" method of searching 
  105. //for matching usermeta is retained for backwards compatibility with old 3rd party hooks which may've relied on it. 
  106. //Originally, $wp_users contained the full list of users (not just those with matching usermeta). 
  107. $jfb_log .= "WP: Searching " . count($wp_users) . " existing candidates by meta...\n"; 
  108. $user_login_id = false; 
  109. foreach ($wp_users as $wp_user) 
  110. $meta_uid = get_user_meta($wp_user->ID, $jfb_uid_meta_name, true); 
  111. if( $meta_uid && $meta_uid == $fb_uid ) 
  112. $user_data = get_userdata($wp_user->ID); 
  113. $user_login_id = $wp_user->ID; 
  114. $user_login_name = $user_data->user_login; 
  115. $jfb_log .= "WP: Found existing user by meta (" . $user_login_name . ")\n"; 
  116. break; 
  117.  
  118.  
  119. //Next, try to lookup their email directly (via Wordpress). Obviously this will only work if they've revealed 
  120. //their "real" address (vs denying access, or changing it to a "proxy" in the popup) 
  121. if ( !$user_login_id && $userRevealedEmail ) 
  122. $jfb_log .= "WP: Searching for user by email address...\n"; 
  123. if ( $wp_user = get_user_by('email', $fbuser['email']) ) 
  124. $user_login_id = $wp_user->ID; 
  125. $user_data = get_userdata($wp_user->ID); 
  126. $user_login_name = $user_data->user_login; 
  127. $jfb_log .= "WP: Found existing user (" . $user_login_name . ") by email (" . $fbuser['email'] . ")\n"; 
  128.  
  129.  
  130. //If we found an existing user, check if they'd previously denied access to their email but have now allowed it. 
  131. //If so, we'll want to update their WP account with their *real* email. 
  132. global $jfb_default_email; 
  133. if( $user_login_id ) 
  134. //Check 1: It was previously denied, but is now allowed 
  135. $updateEmail = false; 
  136. if( strpos($user_data->user_email, $jfb_default_email) !== FALSE && strpos($fbuser['email'], $jfb_default_email) === FALSE ) 
  137. $jfb_log .= "WP: Previously DENIED email has now been allowed; updating to (".$fbuser['email'].")\n"; 
  138. $updateEmail = true; 
  139. //Check 2: It was previously allowed, but only as an anonymous proxy. They've now revealed their "true" email. 
  140. if( strpos($user_data->user_email, "@proxymail.facebook.com") !== FALSE && strpos($fbuser['email'], "@proxymail.facebook.com") === FALSE ) 
  141. $jfb_log .= "WP: Previously PROXIED email has now been allowed; updating to (".$fbuser['email'].")\n"; 
  142. $updateEmail = true; 
  143. if( $updateEmail ) 
  144. $user_upd = array(); 
  145. $user_upd['ID'] = $user_login_id; 
  146. $user_upd['user_email'] = $fbuser['email']; 
  147. wp_update_user($user_upd); 
  148.  
  149. //Run a hook when an existing user logs in 
  150. $jfb_log .= "WP: Running action wpfb_existing_user\n"; 
  151. do_action('wpfb_existing_user', array('WP_ID' => $user_login_id, 'FB_ID' => $fb_uid, 'WP_UserData' => $user_data, 'access_token'=>$access_token) ); 
  152.  
  153.  
  154. //If we still don't have a user_login_id, the FB user who's logging in has never been to this blog. 
  155. //We'll auto-register them a new account. Note that if they haven't allowed email permissions, the 
  156. //account we register will have a bogus email address (but that's OK, since we still know their Facebook ID) 
  157. if( !$user_login_id ) 
  158. $jfb_log .= "WP: No user found. Automatically registering (FB_". $fb_uid . ")\n"; 
  159. $user_data = array(); 
  160. $user_data['user_login'] = "FB_" . $fb_uid; 
  161. $user_data['user_pass'] = wp_generate_password(); 
  162. $user_data['first_name'] = $fbuser['first_name']; 
  163. $user_data['last_name'] = $fbuser['last_name']; 
  164. $user_data['user_url'] = $fbuser["profile_url"]; 
  165. $user_data['user_email'] = $fbuser["email"]; 
  166.  
  167. //Nicename is a sanitized copy of the username; it's not visible/editable from the admin panel. It's what's used for author links. 
  168. $user_data['user_nicename'] = sanitize_title($user_data['user_login']); 
  169.  
  170. //Display_name is selectable as the "Display name publicly as" dropdown on the profile page. 
  171. //BP also duplicates this to the primary XProfile "name" field when a new user is registered. 
  172. $user_data['display_name'] = $fbuser['first_name'] . " " . $fbuser['last_name']; 
  173.  
  174. //Run a filter so the user can be modified to something different before registration 
  175. //NOTE: If the user has selected "pretty names", this'll change FB_xxx to i.e. "John.Smith" 
  176. $jfb_log .= "WP: Applying filters wpfb_insert_user/wpfb_inserting_user\n"; 
  177. $user_data = apply_filters('wpfb_insert_user', $user_data, $fbuser ); 
  178. $user_data = apply_filters('wpfb_inserting_user', $user_data, array('WP_ID' => $user_login_id, 'FB_ID' => $fb_uid, 'FB_UserData' => $fbuser, 'access_token'=>$access_token) ); 
  179.  
  180. //Insert a new user to our database and make sure it worked 
  181. $user_login_id = wp_insert_user($user_data); 
  182. if( is_wp_error($user_login_id) ) 
  183. $errMsg = "Error: wp_insert_user failed!<br /><br />"; 
  184. $errMsg .= __("If you get thiserrorwhile running Wordpress MultiSite, it means you'll need to purchase the premium addon to enable full MultiSite support. Please see here for more information:", 'wp-fb-autoconnect'); 
  185. $errMsg .= " <a href=\"$jfb_homepage#premium\"><b>Premium Addon</b></a><br/>"; 
  186. $errMsg .= __("If you're NOT using MultiSite, please report this bug to the plugin author on the support page:", 'wp-fb-autoconnect'); 
  187. $errMsg .= " <a href=\"$jfb_homepage#feedback\">$jfb_homepage</a>.<br /><br />"; 
  188. $errMsg .= "Message: " . (method_exists($user_login_id, 'get_error_message')?$user_login_id->get_error_message():"Undefined") . "<br />"; 
  189. $errMsg .= "Allow Multisite: " . (defined('WP_ALLOW_MULTISITE')?constant('WP_ALLOW_MULTISITE'):"Undefined") . "<br />"; 
  190. $errMsg .= "Is Multisite: " . (function_exists('is_multisite')?is_multisite():"Undefined") . "<br />"; 
  191. $user_data['user_pass'] = '(Removed)'; 
  192. $errMsg .= "Userdata: " . print_r($user_data, true); 
  193. j_die($errMsg); 
  194.  
  195. //Success! Notify the site admin. 
  196. //(Implementation comes from pre-4.3's version of wp_new_user_notification) 
  197. //See: https://core.trac.wordpress.org/ticket/33209#comment:12 
  198. $user_login_name = $user_data['user_login']; 
  199. $user = get_userdata( $user_login_id ); 
  200. $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES); 
  201. $message = sprintf(__('New user registration on your site %s:'), $blogname) . "\r\n\r\n"; 
  202. $message .= sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n"; 
  203. $message .= sprintf(__('E-mail: %s'), $user->user_email) . "\r\n"; 
  204. @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), $blogname), $message); 
  205.  
  206. //Run an action so i.e. usermeta can be added to a user after registration 
  207. $jfb_log .= "WP: Running action wpfb_inserted_user\n"; 
  208. do_action('wpfb_inserted_user', array('WP_ID' => $user_login_id, 'FB_ID' => $fb_uid, 'WP_UserData' => $user_data, 'access_token'=>$access_token) ); 
  209.  
  210. //Tag the user with our meta so we can recognize them next time, without resorting to email hashes 
  211. global $jfb_uid_meta_name; 
  212. update_user_meta($user_login_id, $jfb_uid_meta_name, $fb_uid); 
  213. $jfb_log .= "WP: Updated usermeta ($jfb_uid_meta_name -> $fb_uid)\n"; 
  214.  
  215. //As of Graph API v2.0, the userID might be a scoped userID - not a "real" userID. Thus, we can no longer infer the profile URL 
  216. //from the ID alone, so we have to store it separately. 
  217. global $jfb_url_meta_name; 
  218. update_user_meta($user_login_id, $jfb_url_meta_name, $fbuser["profile_url"]); 
  219. $jfb_log .= "WP: Updated usermeta ($jfb_url_meta_name -> " . $fbuser["profile_url"] . ")\n"; 
  220.  
  221. //Also store the user's facebook avatar(s), in case the user wants to use them later 
  222. if( $fbuser['pic_square'] ) 
  223. if( isset($fbuser['pic_square']['data']['url']) ) $avatarThumb = $fbuser['pic_square']['data']['url'];  
  224. else $avatarThumb = $fbuser['pic_square']; 
  225. if( isset($fbuser['pic_big']['data']['url']) ) $avatarFull = $fbuser['pic_big']['data']['url']; 
  226. else $avatarFull = $fbuser['pic_big']; 
  227. update_user_meta($user_login_id, 'facebook_avatar_full', $avatarFull); 
  228. update_user_meta($user_login_id, 'facebook_avatar_thumb', $avatarThumb); 
  229. $jfb_log .= "WP: Updated small avatar ($avatarThumb)\n"; 
  230. $jfb_log .= "WP: Updated large avatar ($avatarFull)\n";  
  231. else 
  232. update_user_meta($user_login_id, 'facebook_avatar_thumb', ''); 
  233. update_user_meta($user_login_id, 'facebook_avatar_full', ''); 
  234. $jfb_log .= "FB: User does not have a profile picture; clearing cached avatar (if present).\n"; 
  235.  
  236. //Log them in 
  237. $rememberme = apply_filters('wpfb_rememberme', isset($_POST['rememberme'])&&$_POST['rememberme']); 
  238. wp_set_auth_cookie( $user_login_id, $rememberme ); 
  239.  
  240. //Run a custom action. You can use this to modify a logging-in user however you like,  
  241. //i.e. add them to a "Recent FB Visitors" log, assign a role if they're friends with you on Facebook, etc. 
  242. $jfb_log .= "WP: Running action wpfb_login\n"; 
  243. do_action('wpfb_login', array('WP_ID' => $user_login_id, 'FB_ID' => $fb_uid, 'access_token'=>$access_token, 'fb_userdata'=>$fbuser) ); 
  244. do_action('wp_login', $user_login_name, get_userdata($user_login_id)); 
  245.  
  246.  
  247. //Email logs if requested 
  248. $jfb_log .= "Login complete (rememberme=" . ($rememberme?"yes":"no") . ")\n"; 
  249. $jfb_log .= " WP User : $user_login_name (" . admin_url("user-edit.php?user_id=$user_login_id") . ")\n"; 
  250. $jfb_log .= " FB User : " . $fbuser['name'] . " (" . $fbuser["profile_url"] . ")\n"; 
  251. $jfb_log .= " Redirect: " . $redirectTo . "\n"; 
  252. j_mail("FB Login: " . $user_login_name . " -> " . get_bloginfo('name')); 
  253.  
  254.  
  255. //Redirect the user back to where they were 
  256. global $opt_jfb_delay_redir; 
  257. $delay_redirect = get_option($opt_jfb_delay_redir); 
  258. if( !isset($delay_redirect) || !$delay_redirect ) 
  259. header("Location: " . $redirectTo); 
  260. exit; 
  261. ?> 
  262. <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> 
  263. <html> 
  264. <head> 
  265. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
  266. <title>Logging In...</title> 
  267. </head> 
  268. <body> 
  269. <?php $jfb_log .= "\n---REQUEST:---\n" . print_r($_REQUEST, true); ?>  
  270. <?php echo "<pre>".$jfb_log."</pre>" ?> 
  271. <?php echo '<a href="'.$redirectTo.'">Continue</a>'?> 
  272. </body> 
  273. </html> 
  274. <?php