1<?php 2/** 3 * DokuWiki Plugin oauth (Auth Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11 12class auth_plugin_oauth extends auth_plugin_authplain { 13 14 /** 15 * Constructor 16 * 17 * Sets capabilities. 18 */ 19 public function __construct() { 20 parent::__construct(); 21 22 $this->cando['external'] = true; 23 } 24 25 /** 26 * Handle the login 27 * 28 * This either trusts the session data (if any), processes the second oAuth step or simply 29 * executes a normal plugin against local users. 30 * 31 * @param string $user 32 * @param string $pass 33 * @param bool $sticky 34 * @return bool 35 */ 36 function trustExternal($user, $pass, $sticky = false) { 37 global $INPUT; 38 global $conf; 39 global $USERINFO; 40 41 $servicename = $INPUT->str('oa'); 42 43 // check session for existing oAuth login data 44 $session = $_SESSION[DOKU_COOKIE]['auth']; 45 if(!$servicename && isset($session['oauth'])) { 46 $servicename = $session['oauth']; 47 // check if session data is still considered valid 48 if(($session['time'] >= time() - $conf['auth_security_timeout']) && 49 ($session['buid'] == auth_browseruid()) 50 ) { 51 52 $_SERVER['REMOTE_USER'] = $session['user']; 53 $USERINFO = $session['info']; 54 return true; 55 } 56 } 57 58 // either we're in oauth login or a previous log needs to be rechecked 59 if($servicename) { 60 /** @var helper_plugin_oauth $hlp */ 61 $hlp = plugin_load('helper', 'oauth'); 62 $service = $hlp->loadService($servicename); 63 if(is_null($service)) return false; 64 65 // get the token 66 if($service->checkToken()) { 67 $uinfo = $service->getUser(); 68 69 // see if the user is known already 70 $user = $this->getUserByEmail($uinfo['mail']); 71 if($user) { 72 $sinfo = $this->getUserData($user); 73 $uinfo['user'] = $user; 74 $uinfo['name'] = $sinfo['name']; 75 $uinfo['grps'] = array_merge((array) $uinfo['grps'], $sinfo['grps']); 76 } else { 77 // new user, create him - making sure the login is unique by adding a number if needed 78 $user = $uinfo['user']; 79 $count = ''; 80 while($this->getUserData($user.$count)) { 81 if($count) { 82 $count++; 83 } else { 84 $count = 1; 85 } 86 } 87 $user = $user.$count; 88 $uinfo['user'] = $user; 89 $uinfo['grps'] = (array) $uinfo['grps']; 90 $uinfo['grps'][] = $conf['defaultgroup']; 91 92 $this->createUser($user, auth_pwgen($user), $uinfo['name'], $uinfo['mail'], $uinfo['grps']); 93 } 94 95 // set user session 96 $this->setUserSession($uinfo, $servicename); 97 return true; 98 } 99 100 return false; // something went wrong during oAuth login 101 } 102 103 // do the "normal" plain auth login via form 104 return auth_login($user, $pass, $sticky); 105 } 106 107 /** 108 * @param array $data 109 * @param string $service 110 */ 111 protected function setUserSession($data, $service) { 112 global $USERINFO; 113 global $conf; 114 115 // set up groups 116 if(!is_array($data['grps'])) { 117 $data['grps'] = array(); 118 } 119 $data['grps'][] = $this->cleanGroup($service); 120 $data['grps'] = array_unique($data['grps']); 121 122 $USERINFO = $data; 123 $_SERVER['REMOTE_USER'] = $data['user']; 124 $_SESSION[DOKU_COOKIE]['auth']['user'] = $data['user']; 125 $_SESSION[DOKU_COOKIE]['auth']['pass'] = $data['pass']; 126 $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 127 $_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid(); 128 $_SESSION[DOKU_COOKIE]['auth']['time'] = time(); 129 $_SESSION[DOKU_COOKIE]['auth']['oauth'] = $service; 130 } 131 132 /** 133 * Unset additional stuff in session on logout 134 */ 135 public function logOff() { 136 parent::logOff(); 137 138 if(isset($_SESSION[DOKU_COOKIE]['auth']['buid'])) { 139 unset($_SESSION[DOKU_COOKIE]['auth']['buid']); 140 } 141 if(isset($_SESSION[DOKU_COOKIE]['auth']['time'])) { 142 unset($_SESSION[DOKU_COOKIE]['auth']['time']); 143 } 144 if(isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) { 145 unset($_SESSION[DOKU_COOKIE]['auth']['oauth']); 146 } 147 } 148 149 /** 150 * Find a user by his email address 151 * 152 * @param $mail 153 * @return bool|string 154 */ 155 protected function getUserByEmail($mail) { 156 if($this->users === null) $this->_loadUserData(); 157 $mail = strtolower($mail); 158 159 foreach($this->users as $user => $uinfo) { 160 if(strtolower($uinfo['mail']) == $mail) return $user; 161 } 162 163 return false; 164 } 165 166 /** 167 * Enhance function to check aainst duplicate emails 168 * 169 * @param string $user 170 * @param string $pwd 171 * @param string $name 172 * @param string $mail 173 * @param null $grps 174 * @return bool|null|string 175 */ 176 public function createUser($user, $pwd, $name, $mail, $grps = null) { 177 if($this->getUserByEmail($mail)) { 178 msg($this->getLang('emailduplicate'), -1); 179 return false; 180 } 181 182 return parent::createUser($user, $pwd, $name, $mail, $grps); 183 } 184 185 /** 186 * Enhance function to check aainst duplicate emails 187 * 188 * @param string $user 189 * @param array $changes 190 * @return bool 191 */ 192 public function modifyUser($user, $changes) { 193 if(isset($changes['mail']) && $this->getUserByEmail($changes['mail'])) { 194 msg($this->getLang('emailduplicate'), -1); 195 return false; 196 } 197 198 return parent::modifyUser($user, $changes); 199 } 200 201} 202 203// vim:ts=4:sw=4:et: