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 $uinfo['user'] = $this->cleanUser((string) $uinfo['user']); 70 if(!$uinfo['name']) $uinfo['name'] = $uinfo['user']; 71 72 if(!$uinfo['user'] || !$uinfo['mail']) { 73 msg("$servicename did not provide the needed user info. Can't log you in", -1); 74 return false; 75 } 76 77 // see if the user is known already 78 $user = $this->getUserByEmail($uinfo['mail']); 79 if($user) { 80 $sinfo = $this->getUserData($user); 81 $uinfo['user'] = $user; 82 $uinfo['name'] = $sinfo['name']; 83 $uinfo['grps'] = array_merge((array) $uinfo['grps'], $sinfo['grps']); 84 } else { 85 // new user, create him - making sure the login is unique by adding a number if needed 86 $user = $uinfo['user']; 87 $count = ''; 88 while($this->getUserData($user.$count)) { 89 if($count) { 90 $count++; 91 } else { 92 $count = 1; 93 } 94 } 95 $user = $user.$count; 96 $uinfo['user'] = $user; 97 $uinfo['grps'] = (array) $uinfo['grps']; 98 $uinfo['grps'][] = $conf['defaultgroup']; 99 100 $this->createUser($user, auth_pwgen($user), $uinfo['name'], $uinfo['mail'], $uinfo['grps']); 101 } 102 103 // set user session 104 $this->setUserSession($uinfo, $servicename); 105 return true; 106 } 107 108 return false; // something went wrong during oAuth login 109 } 110 111 // do the "normal" plain auth login via form 112 return auth_login($user, $pass, $sticky); 113 } 114 115 /** 116 * @param array $data 117 * @param string $service 118 */ 119 protected function setUserSession($data, $service) { 120 global $USERINFO; 121 global $conf; 122 123 // set up groups 124 if(!is_array($data['grps'])) { 125 $data['grps'] = array(); 126 } 127 $data['grps'][] = $this->cleanGroup($service); 128 $data['grps'] = array_unique($data['grps']); 129 130 $USERINFO = $data; 131 $_SERVER['REMOTE_USER'] = $data['user']; 132 $_SESSION[DOKU_COOKIE]['auth']['user'] = $data['user']; 133 $_SESSION[DOKU_COOKIE]['auth']['pass'] = $data['pass']; 134 $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 135 $_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid(); 136 $_SESSION[DOKU_COOKIE]['auth']['time'] = time(); 137 $_SESSION[DOKU_COOKIE]['auth']['oauth'] = $service; 138 } 139 140 /** 141 * Unset additional stuff in session on logout 142 */ 143 public function logOff() { 144 parent::logOff(); 145 146 if(isset($_SESSION[DOKU_COOKIE]['auth']['buid'])) { 147 unset($_SESSION[DOKU_COOKIE]['auth']['buid']); 148 } 149 if(isset($_SESSION[DOKU_COOKIE]['auth']['time'])) { 150 unset($_SESSION[DOKU_COOKIE]['auth']['time']); 151 } 152 if(isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) { 153 unset($_SESSION[DOKU_COOKIE]['auth']['oauth']); 154 } 155 } 156 157 /** 158 * Find a user by his email address 159 * 160 * @param $mail 161 * @return bool|string 162 */ 163 protected function getUserByEmail($mail) { 164 if($this->users === null) $this->_loadUserData(); 165 $mail = strtolower($mail); 166 167 foreach($this->users as $user => $uinfo) { 168 if(strtolower($uinfo['mail']) == $mail) return $user; 169 } 170 171 return false; 172 } 173 174 /** 175 * Enhance function to check aainst duplicate emails 176 * 177 * @param string $user 178 * @param string $pwd 179 * @param string $name 180 * @param string $mail 181 * @param null $grps 182 * @return bool|null|string 183 */ 184 public function createUser($user, $pwd, $name, $mail, $grps = null) { 185 if($this->getUserByEmail($mail)) { 186 msg($this->getLang('emailduplicate'), -1); 187 return false; 188 } 189 190 return parent::createUser($user, $pwd, $name, $mail, $grps); 191 } 192 193 /** 194 * Enhance function to check aainst duplicate emails 195 * 196 * @param string $user 197 * @param array $changes 198 * @return bool 199 */ 200 public function modifyUser($user, $changes) { 201 if(isset($changes['mail']) && $this->getUserByEmail($changes['mail'])) { 202 msg($this->getLang('emailduplicate'), -1); 203 return false; 204 } 205 206 return parent::modifyUser($user, $changes); 207 } 208 209} 210 211// vim:ts=4:sw=4:et: