137d2401aSAnna Dabrowska<?php 237d2401aSAnna Dabrowska 3*290e9b1fSAndreas Gohruse dokuwiki\Extension\ActionPlugin; 4*290e9b1fSAndreas Gohruse dokuwiki\Extension\EventHandler; 5*290e9b1fSAndreas Gohruse dokuwiki\Extension\Event; 61fad6988SAndreas Gohruse dokuwiki\Form\Form; 7e170f465SAndreas Gohruse dokuwiki\plugin\oauth\OAuthManager; 837d2401aSAnna Dabrowskause OAuth\Common\Http\Exception\TokenResponseException; 937d2401aSAnna Dabrowska 1037d2401aSAnna Dabrowska/** 1137d2401aSAnna Dabrowska * DokuWiki Plugin oauth (Action Component) 1237d2401aSAnna Dabrowska * 1374b4d4a4SAndreas Gohr * This adds buttons to the login page and initializes the oAuth flow by redirecting the user 1474b4d4a4SAndreas Gohr * to the third party service 1574b4d4a4SAndreas Gohr * 1637d2401aSAnna Dabrowska * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 1737d2401aSAnna Dabrowska * @author Andreas Gohr <andi@splitbrain.org> 1837d2401aSAnna Dabrowska */ 19*290e9b1fSAndreas Gohrclass action_plugin_oauth_login extends ActionPlugin 2037d2401aSAnna Dabrowska{ 2137d2401aSAnna Dabrowska /** @var helper_plugin_oauth */ 2237d2401aSAnna Dabrowska protected $hlp; 2337d2401aSAnna Dabrowska 2437d2401aSAnna Dabrowska /** 2537d2401aSAnna Dabrowska * Constructor 2637d2401aSAnna Dabrowska * 2737d2401aSAnna Dabrowska * Initializes the helper 2837d2401aSAnna Dabrowska */ 2937d2401aSAnna Dabrowska public function __construct() 3037d2401aSAnna Dabrowska { 3137d2401aSAnna Dabrowska $this->hlp = plugin_load('helper', 'oauth'); 3237d2401aSAnna Dabrowska } 3337d2401aSAnna Dabrowska 3437d2401aSAnna Dabrowska /** 3537d2401aSAnna Dabrowska * Registers a callback function for a given event 3637d2401aSAnna Dabrowska * 37*290e9b1fSAndreas Gohr * @param EventHandler $controller DokuWiki's event controller object 3837d2401aSAnna Dabrowska * @return void 3937d2401aSAnna Dabrowska */ 40*290e9b1fSAndreas Gohr public function register(EventHandler $controller) 4137d2401aSAnna Dabrowska { 4237d2401aSAnna Dabrowska global $conf; 4337d2401aSAnna Dabrowska if ($conf['authtype'] != 'oauth') return; 4437d2401aSAnna Dabrowska 4537d2401aSAnna Dabrowska $conf['profileconfirm'] = false; // password confirmation doesn't work with oauth only users 4637d2401aSAnna Dabrowska 4737d2401aSAnna Dabrowska $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handleStart'); 481fad6988SAndreas Gohr $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handleOldLoginForm'); // @deprecated 491fad6988SAndreas Gohr $controller->register_hook('FORM_LOGIN_OUTPUT', 'BEFORE', $this, 'handleLoginForm'); 5037d2401aSAnna Dabrowska $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleDoLogin'); 51542bb44dSAndreas Gohr $controller->register_hook('ACTION_DENIED_TPLCONTENT', 'BEFORE', $this, 'handleDeniedForm'); 5237d2401aSAnna Dabrowska } 5337d2401aSAnna Dabrowska 5437d2401aSAnna Dabrowska /** 5537d2401aSAnna Dabrowska * Start an oAuth login or restore environment after successful login 5637d2401aSAnna Dabrowska * 57*290e9b1fSAndreas Gohr * @param Event $event 5837d2401aSAnna Dabrowska * @return void 5937d2401aSAnna Dabrowska */ 60*290e9b1fSAndreas Gohr public function handleStart(Event $event) 6137d2401aSAnna Dabrowska { 6237d2401aSAnna Dabrowska global $INPUT; 6337d2401aSAnna Dabrowska 6437d2401aSAnna Dabrowska // see if a login needs to be started 6537d2401aSAnna Dabrowska $servicename = $INPUT->str('oauthlogin'); 666d9a8a49SAndreas Gohr if (!$servicename) return; 676d9a8a49SAndreas Gohr 686d9a8a49SAndreas Gohr try { 69e170f465SAndreas Gohr $om = new OAuthManager(); 706d9a8a49SAndreas Gohr $om->startFlow($servicename); 716d9a8a49SAndreas Gohr } catch (TokenResponseException | Exception $e) { 726d9a8a49SAndreas Gohr $this->hlp->showException($e, 'login failed'); 736d9a8a49SAndreas Gohr } 7437d2401aSAnna Dabrowska } 7537d2401aSAnna Dabrowska 7637d2401aSAnna Dabrowska /** 77d9be1cb5SAnna Dabrowska * Add the oAuth login links to login form 7837d2401aSAnna Dabrowska * 79*290e9b1fSAndreas Gohr * @param Event $event event object by reference 8037d2401aSAnna Dabrowska * @return void 8174b4d4a4SAndreas Gohr * @deprecated can be removed in the future 8237d2401aSAnna Dabrowska */ 83*290e9b1fSAndreas Gohr public function handleOldLoginForm(Event $event) 8437d2401aSAnna Dabrowska { 8537d2401aSAnna Dabrowska /** @var Doku_Form $form */ 8637d2401aSAnna Dabrowska $form = $event->data; 871fad6988SAndreas Gohr $html = $this->prepareLoginButtons(); 881fad6988SAndreas Gohr if (!$html) return; 891fad6988SAndreas Gohr 9045fc651dSAnna Dabrowska // remove login form if single service is set 9145fc651dSAnna Dabrowska $singleService = $this->getConf('singleService'); 9245fc651dSAnna Dabrowska if ($singleService) { 9345fc651dSAnna Dabrowska $form->_content = []; 9445fc651dSAnna Dabrowska } 9545fc651dSAnna Dabrowska 961fad6988SAndreas Gohr $form->_content[] = form_openfieldset( 971fad6988SAndreas Gohr [ 981fad6988SAndreas Gohr '_legend' => $this->getLang('loginwith'), 991fad6988SAndreas Gohr 'class' => 'plugin_oauth', 1001fad6988SAndreas Gohr ] 1011fad6988SAndreas Gohr ); 1021fad6988SAndreas Gohr $form->_content[] = $html; 1031fad6988SAndreas Gohr $form->_content[] = form_closefieldset(); 1041fad6988SAndreas Gohr } 1051fad6988SAndreas Gohr 1061fad6988SAndreas Gohr /** 1071fad6988SAndreas Gohr * Add the oAuth login links to login form 1081fad6988SAndreas Gohr * 109*290e9b1fSAndreas Gohr * @param Event $event event object by reference 1101fad6988SAndreas Gohr * @return void 11174b4d4a4SAndreas Gohr * @deprecated can be removed in the future 1121fad6988SAndreas Gohr */ 113*290e9b1fSAndreas Gohr public function handleLoginForm(Event $event) 1141fad6988SAndreas Gohr { 1151fad6988SAndreas Gohr /** @var Form $form */ 1161fad6988SAndreas Gohr $form = $event->data; 1171fad6988SAndreas Gohr $html = $this->prepareLoginButtons(); 1181fad6988SAndreas Gohr if (!$html) return; 1191fad6988SAndreas Gohr 12045fc651dSAnna Dabrowska // remove login form if single service is set 12145fc651dSAnna Dabrowska $singleService = $this->getConf('singleService'); 12245fc651dSAnna Dabrowska if ($singleService) { 12345fc651dSAnna Dabrowska do { 12445fc651dSAnna Dabrowska $form->removeElement(0); 12545fc651dSAnna Dabrowska } while ($form->elementCount() > 0); 12645fc651dSAnna Dabrowska } 12745fc651dSAnna Dabrowska 1281fad6988SAndreas Gohr $form->addFieldsetOpen($this->getLang('loginwith'))->addClass('plugin_oauth'); 1291fad6988SAndreas Gohr $form->addHTML($html); 1301fad6988SAndreas Gohr $form->addFieldsetClose(); 1311fad6988SAndreas Gohr } 1321fad6988SAndreas Gohr 1331fad6988SAndreas Gohr /** 1341fad6988SAndreas Gohr * Create HTML for the various login buttons 1351fad6988SAndreas Gohr * 1361fad6988SAndreas Gohr * @return string the HTML 1371fad6988SAndreas Gohr */ 13874b4d4a4SAndreas Gohr protected function prepareLoginButtons() 13974b4d4a4SAndreas Gohr { 14037d2401aSAnna Dabrowska $html = ''; 14137d2401aSAnna Dabrowska 14237d2401aSAnna Dabrowska $validDomains = $this->hlp->getValidDomains(); 14337d2401aSAnna Dabrowska 14437d2401aSAnna Dabrowska if (count($validDomains) > 0) { 1456f3a59e8SAndreas Gohr $html .= '<p class="plugin-oauth-emailrestriction">' . sprintf( 1466f3a59e8SAndreas Gohr $this->getLang('eMailRestricted'), 147*290e9b1fSAndreas Gohr '<b>' . implode(', ', $validDomains) . '</b>' 1486f3a59e8SAndreas Gohr ) . '</p>'; 14937d2401aSAnna Dabrowska } 15037d2401aSAnna Dabrowska 151ef19de6cSAndreas Gohr $html .= '<div>'; 15237d2401aSAnna Dabrowska foreach ($this->hlp->listServices() as $service) { 15337d2401aSAnna Dabrowska $html .= $service->loginButton(); 15437d2401aSAnna Dabrowska } 155ef19de6cSAndreas Gohr $html .= '</div>'; 15637d2401aSAnna Dabrowska 1571fad6988SAndreas Gohr return $html; 15837d2401aSAnna Dabrowska } 15937d2401aSAnna Dabrowska 16037d2401aSAnna Dabrowska /** 16137d2401aSAnna Dabrowska * When singleservice is wanted, do not show login, but execute login right away 16237d2401aSAnna Dabrowska * 163*290e9b1fSAndreas Gohr * @param Event $event 16437d2401aSAnna Dabrowska * @return bool 16537d2401aSAnna Dabrowska */ 166*290e9b1fSAndreas Gohr public function handleDoLogin(Event $event) 16737d2401aSAnna Dabrowska { 16837d2401aSAnna Dabrowska global $ID; 169caf913c3SAndreas Gohr global $INPUT; 17037d2401aSAnna Dabrowska 171caf913c3SAndreas Gohr if ($event->data != 'login' && $event->data != 'denied') return true; 17237d2401aSAnna Dabrowska 17337d2401aSAnna Dabrowska $singleService = $this->getConf('singleService'); 17437d2401aSAnna Dabrowska if (!$singleService) return true; 17537d2401aSAnna Dabrowska 176caf913c3SAndreas Gohr if ($INPUT->server->str('REMOTE_USER') !== '') { 177caf913c3SAndreas Gohr // already logged in 178caf913c3SAndreas Gohr return true; 179caf913c3SAndreas Gohr } 180caf913c3SAndreas Gohr 18137d2401aSAnna Dabrowska $enabledServices = $this->hlp->listServices(); 18237d2401aSAnna Dabrowska if (count($enabledServices) !== 1) { 18337d2401aSAnna Dabrowska msg($this->getLang('wrongConfig'), -1); 18437d2401aSAnna Dabrowska return false; 18537d2401aSAnna Dabrowska } 18637d2401aSAnna Dabrowska 18737d2401aSAnna Dabrowska $service = array_shift($enabledServices); 18837d2401aSAnna Dabrowska 18937d2401aSAnna Dabrowska $url = wl($ID, ['oauthlogin' => $service->getServiceID()], true, '&'); 19037d2401aSAnna Dabrowska send_redirect($url); 19137d2401aSAnna Dabrowska return true; // never reached 19237d2401aSAnna Dabrowska } 19337d2401aSAnna Dabrowska 194542bb44dSAndreas Gohr /** 195542bb44dSAndreas Gohr * Do not show a login form on restricted pages when SingleService is enabled 196542bb44dSAndreas Gohr * 197542bb44dSAndreas Gohr * This can happen when the user is already logged in, but still doesn't have enough permissions 198542bb44dSAndreas Gohr * 199*290e9b1fSAndreas Gohr * @param Event $event 200542bb44dSAndreas Gohr * @return void 201542bb44dSAndreas Gohr */ 202*290e9b1fSAndreas Gohr public function handleDeniedForm(Event $event) 203542bb44dSAndreas Gohr { 204542bb44dSAndreas Gohr if ($this->getConf('singleService')) { 205542bb44dSAndreas Gohr $event->preventDefault(); 206542bb44dSAndreas Gohr $event->stopPropagation(); 207542bb44dSAndreas Gohr } 208542bb44dSAndreas Gohr } 20937d2401aSAnna Dabrowska} 210