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