1<?php 2/** 3 * Facebook authentication backend 4 * derived from Václav Voborníks FBauth and sentryperm@gmail.coms authgoogle 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Leo Zachl <leo.zachl@gmail.com> 8 */ 9 10define('DOKU_AUTH', dirname(__FILE__)); 11// require_once(DOKU_AUTH.'/basic.class.php'); 12require_once(DOKU_AUTH.'/lib/autoload.php'); 13require_once(DOKU_AUTH.'/dwPersistentData.php'); 14 15// define cookie and session id, append server port when securecookie is configured 16if (!defined('AUTHFACEBOOK_COOKIE')) define('AUTHFACEBOOK_COOKIE', 'SPFB'.md5(DOKU_REL.(($conf['securecookie'])?$_SERVER['SERVER_PORT']:''))); 17 18#define('AUTH_USERFILE',DOKU_CONF.'users.auth.php'); 19 20class auth_plugin_authfacebook extends auth_plugin_authplain { 21 22 var $users = null; 23 var $_pattern = array(); 24 25 var $fbsession = array(); 26 27 public function __construct() { 28 global $conf, $config_cascade; 29 30 parent::__construct(); 31 32 $this->cando['external'] = true; 33 $this->cando['logout'] = true; 34 $this->cando['delUser'] = false; 35 36 $this->success = true; 37 return; 38 39 } 40 41 function trustExternal($user,$pass,$sticky=true ){ 42 global $USERINFO; 43 global $conf; 44 $sticky ? $sticky = true : $sticky = false; //sanity check 45 46 if (!empty($_SESSION[DOKU_COOKIE]['authfacebook']['user'])) { 47 $USERINFO = $_SESSION[DOKU_COOKIE]['authfacebook']['info']; 48 if (!$USERINFO['is_facebook']){ 49 $this->cando['modPass'] = true; 50 $this->cando['delUser'] = true; 51 } 52 $_SERVER['REMOTE_USER'] = $_SESSION[DOKU_COOKIE]['authfacebook']['user']; 53 return true; 54 } 55 56 //get authplain form login info 57 if(!empty($user)){ 58 if($this->checkPass($user,$pass)){ 59 $uinfo = $this->getUserData($user); 60 61 //set user info 62 $USERINFO['name'] = $uinfo['name']; 63 $USERINFO['mail'] = $uinfo['mail']; 64 $USERINFO['grps'] = $uinfo['grps']; 65 $USERINFO['is_facebook'] = false; 66 $USERINFO['pass'] = ''; // $pass; 67 68 //save data in session 69 $_SERVER['REMOTE_USER'] = $uinfo['name']; 70 $_SESSION[DOKU_COOKIE]['authfacebook']['user'] = $user; 71 $_SESSION[DOKU_COOKIE]['authfacebook']['info'] = $USERINFO; 72 return true; 73 } else { 74 //invalid credentials - log off 75 msg($this->getLang('badlogin'),-1); 76 return false; 77 } 78 } 79 80 if ($_COOKIE[AUTHFACEBOOK_COOKIE]) { 81 $_SESSION[DOKU_COOKIE]['authfacebook']['token'] = $_COOKIE[AUTHFACEBOOK_COOKIE]; 82 } 83 84 if (($appId = $this->getConf('applicationID')) && ($appSecret = $this->getConf('applicationSecret'))) { 85 $fb = new Facebook\Facebook(array( 86 'app_id' => $appId, 87 'app_secret' => $appSecret, 88 'default_graph_version' => 'v2.12', 89 'persistent_data_handler' => new MyDokuWikiPersistentDataHandler(), 90 )); 91 $helper = $fb->getRedirectLoginHelper(); 92 93 if (isset($_GET['code'])) { 94 //get token 95 try { 96 $accessToken = $helper->getAccessToken(); 97 if ($accessToken) { 98 //save token in session 99 $_SESSION[DOKU_COOKIE]['authfacebook']['token'] = $accessToken; 100 //save token in cookies 101 $this->_updateCookie($_SESSION[DOKU_COOKIE]['authfacebook']['token'], time() + 60 * 60 * 24 * 365); 102 try { 103 $response = $fb->get('/me?fields=id,name,email', $accessToken); 104 } catch (FacebookApiException $e) { 105 error_log("2: " . $e); 106 } 107 if ($response) { 108 $me = $response->getGraphUser(); 109 110 // the FB-App is only allowed to read the groups of the App-Admin 111 $response = $fb->get('/me/permissions', $accessToken); 112 $permissions = $response->getGraphEdge(); 113 if ($me['id'] == $this->getConf('appAdmin')) 114 $this->getFacebookGroups($fb, $permissions, $accessToken); 115 116 $grantedpermissions = array(); 117 foreach($permissions as $permission) 118 if ($permission['status'] == 'granted') 119 $grantedpermissions[] = $permission['permission']; 120 $_SESSION[DOKU_COOKIE]['authfacebook']['permissions'] = $grantedpermissions; 121 122 $USERINFO['name'] = $me['name']; 123 $USERINFO['mail'] = $me['email']; 124 $USERINFO['is_facebook'] = true; 125 $USERINFO['grps'] = array( $this->getConf('defaultgroup')); 126 if (($fbgroupid = $this->getConf('fbgid2group')) != ''){ 127 if ($fbg2user = json_decode($fbgroupid,TRUE)){ 128 require(DOKU_CONF.'/fb_groups.php'); 129 foreach($fbg2user as $id => $group){ 130 if (isset($fb_groups[$id]) && isset($fb_groups[$id][$me['id']])) $USERINFO['grps'][] = $group; 131 } 132 } 133 } 134 if (in_array($me['id'],json_decode($this->getConf('superuser')))) 135 $USERINFO['grps'][] = 'admin'; 136 137 touch(DOKU_CONF.'/fb_ids.php'); 138 $fb_ids_fd = fopen(DOKU_CONF.'/fb_ids.php','r+'); 139 $fb_ids_lock = flock($fb_ids_fd, LOCK_EX | LOCK_NB); 140 require(DOKU_CONF.'/fb_ids.php'); 141 142 if (isset($fb_ids[$me['id']])){ 143 $user = $fb_ids[$me['id']]; 144 } else { 145 $plain_user = $this->retrieveUsers(0,0,array('mail' => '^'.$me['email'].'$')); 146 if (count($plain_user) > 0) 147 $user = reset(array_keys($plain_user)); 148 else { 149 if (!empty($me['email'])) 150 $user = strtolower(reset(explode('@',$me['email']))); 151 else 152 $user = preg_replace("/[^a-z0-9]/","_",strtolower(trim(basename(stripslashes(iconv("utf8","ascii//translit",strtr($me['name'],' ','.')))), ".\x00..\x20"))); 153 $plain_user = $this->retrieveUsers(0,0,array('user' => '^'.$user.'$')); 154 $ext = ''; $cnt=0; 155 while (count($plain_user) > 0 || in_array($user.$ext,$fb_ids)){ 156 $cnt++; 157 $ext = '-'.$cnt; 158 $plain_user = $this->retrieveUsers(0,0,array('user' => '^'.$user.$ext.'$')); 159 } 160 $user = $user.$ext; 161 $fb_ids[$me['id']] = $user; 162 if ($fb_ids_lock){ 163 ftruncate($fb_ids_fd, 0); // kürze Datei 164 fwrite($fb_ids_fd,"<?php\n\$fb_ids = ".var_export($fb_ids,true).";\n"); 165 fflush($fb_ids_fd); 166 } 167 } 168 } 169 flock($fb_ids_fd, LOCK_UN); 170 fclose($fb_ids_fd); 171 172 $_SESSION[DOKU_COOKIE]['authfacebook']['userid'] = $me['id']; 173 $_SERVER['REMOTE_USER'] = $user; 174 $_SESSION[DOKU_COOKIE]['authfacebook']['user'] = $user; 175 $_SESSION[DOKU_COOKIE]['authfacebook']['pass'] = ''; 176 $_SESSION[DOKU_COOKIE]['authfacebook']['info'] = $USERINFO; 177 178 //redirect to login page 179 header("Location: ".wl('start', array(), true, '&')); 180 die(); 181 182 } //me 183 } else { // FB session 184 $_SESSION[DOKU_COOKIE]['authfacebook']['auth_url'] = $helper->getLoginUrl( 185 wl('start',array('do'=>'login'),true, '&'), 186 explode(',',$this->getConf('scope')) 187 ); 188 } 189 } catch (Exception $e) { 190 $_SESSION[DOKU_COOKIE]['authfacebook']['auth_url'] = $helper->getLoginUrl( 191 wl('start',array('do'=>'login'),true, '&'), 192 explode(',',$this->getConf('scope')) 193 ); 194 msg('1: Auth Facebook Error: '. $e->getFile() .':'.$e->getLine().': '.$e->getMessage()); 195 } 196 } 197 198 if (!isset($_SESSION[DOKU_COOKIE]['authfacebook']['auth_url'])) 199 $_SESSION[DOKU_COOKIE]['authfacebook']['auth_url'] = $helper->getLoginUrl( 200 wl('start',array('do'=>'login'),true, '&'), 201 explode(',',$this->getConf('scope')) 202 ); 203 } 204 205 return false; 206 } 207 208 function logOff(){ 209 unset($_SESSION[DOKU_COOKIE]['authfacebook']['token']); 210 unset($_SESSION[DOKU_COOKIE]['authfacebook']['user']); 211 unset($_SESSION[DOKU_COOKIE]['authfacebook']['info']); 212 unset($_SESSION[DOKU_COOKIE]['authfacebook']['userid']); 213 // clear the cookie 214 $this->_updateCookie('', time() - 600000); 215 if (($appId = $this->getConf('applicationID')) && ($appSecret = $this->getConf('applicationSecret'))) { 216 $fb = new Facebook\Facebook(array( 217 'app_id' => $appId, 218 'app_secret' => $appSecret, 219 'default_graph_version' => 'v2.3', 220 'persistent_data_handler' => new MyDokuWikiPersistentDataHandler(), 221 )); 222 } 223 unset($_SESSION[DOKU_COOKIE]['authfacebook']['auth_url']); 224 } 225 226 function _updateCookie($value, $time) { 227 global $conf; 228 229 $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir']; 230 if (version_compare(PHP_VERSION, '5.2.0', '>')) { 231 setcookie(AUTHFACEBOOK_COOKIE, $value, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true); 232 } else { 233 setcookie(AUTHFACEBOOK_COOKIE, $value, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl())); 234 } 235 } 236 237 private function getFacebookGroups($facebook,$permissions, $accessToken){ 238 if ($mapgroups = json_decode($this->getConf('fbgid2group'),true)){ 239 foreach($permissions as $permission){ 240 if ($permission['permission'] == 'user_managed_groups' && $permission['status'] == 'granted'){ 241 $groups = $facebook->get('/me/groups', $accessToken); 242 $groups = $groups->getGraphEdge(); 243 $usergroups = array(); 244 foreach($groups as $group){ 245 $usergroups[$group['id']] = $group['name']; 246 } 247 if (is_file(DOKU_CONF.'/fb_groups_orig.php')) 248 include(DOKU_CONF.'/fb_groups_orig.php'); 249 else 250 $fb_groups = array(); 251 foreach(array_intersect_key($mapgroups,$usergroups) as $groupid => $groupname){ 252 $group_members = $facebook->get('/'.$groupid.'/members', $accessToken); 253 if (!empty($group_members)) 254 foreach($group_members as $member) 255 $fb_groups[$groupid][$member['id']] = $member['name']; 256 257 } 258 if (!empty($this->getConf('saveAccessKey'))){ 259 $token = "\$fb_token = '".$accessToken."';\n"; 260 } else { 261 $token; 262 } 263 file_put_contents(DOKU_CONF.'/fb_groups.php',"<?php\n\$fb_groups = ".var_export($fb_groups,true).";\n".$token); 264 } 265 } 266 } 267 } 268 269} 270 271//Setup VIM: ex: et ts=2 enc=utf-8 : 272