1<?php 2 3use dokuwiki\Form\Form; 4use dokuwiki\plugin\oauth\OAuthManager; 5use OAuth\Common\Http\Exception\TokenResponseException; 6 7/** 8 * DokuWiki Plugin oauth (Action Component) 9 * 10 * This adds buttons to the login page and initializes the oAuth flow by redirecting the user 11 * to the third party service 12 * 13 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 14 * @author Andreas Gohr <andi@splitbrain.org> 15 */ 16class action_plugin_oauth_login extends DokuWiki_Action_Plugin 17{ 18 /** @var helper_plugin_oauth */ 19 protected $hlp; 20 21 /** 22 * Constructor 23 * 24 * Initializes the helper 25 */ 26 public function __construct() 27 { 28 $this->hlp = plugin_load('helper', 'oauth'); 29 } 30 31 /** 32 * Registers a callback function for a given event 33 * 34 * @param Doku_Event_Handler $controller DokuWiki's event controller object 35 * @return void 36 */ 37 public function register(Doku_Event_Handler $controller) 38 { 39 global $conf; 40 if ($conf['authtype'] != 'oauth') return; 41 42 $conf['profileconfirm'] = false; // password confirmation doesn't work with oauth only users 43 44 $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handleStart'); 45 $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handleOldLoginForm'); // @deprecated 46 $controller->register_hook('FORM_LOGIN_OUTPUT', 'BEFORE', $this, 'handleLoginForm'); 47 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleDoLogin'); 48 } 49 50 /** 51 * Start an oAuth login or restore environment after successful login 52 * 53 * @param Doku_Event $event 54 * @return void 55 */ 56 public function handleStart(Doku_Event $event) 57 { 58 global $INPUT; 59 60 // see if a login needs to be started 61 $servicename = $INPUT->str('oauthlogin'); 62 if (!$servicename) return; 63 64 try { 65 $om = new OAuthManager(); 66 $om->startFlow($servicename); 67 } catch (TokenResponseException|Exception $e) { 68 $this->hlp->showException($e, 'login failed'); 69 } 70 } 71 72 /** 73 * Add the oAuth login links to login form 74 * 75 * @param Doku_Event $event event object by reference 76 * @return void 77 * @deprecated can be removed in the future 78 */ 79 public function handleOldLoginForm(Doku_Event $event) 80 { 81 /** @var Doku_Form $form */ 82 $form = $event->data; 83 $html = $this->prepareLoginButtons(); 84 if (!$html) return; 85 86 // remove login form if single service is set 87 $singleService = $this->getConf('singleService'); 88 if ($singleService) { 89 $form->_content = []; 90 } 91 92 $form->_content[] = form_openfieldset( 93 [ 94 '_legend' => $this->getLang('loginwith'), 95 'class' => 'plugin_oauth', 96 ] 97 ); 98 $form->_content[] = $html; 99 $form->_content[] = form_closefieldset(); 100 } 101 102 /** 103 * Add the oAuth login links to login form 104 * 105 * @param Doku_Event $event event object by reference 106 * @return void 107 * @deprecated can be removed in the future 108 */ 109 public function handleLoginForm(Doku_Event $event) 110 { 111 /** @var Form $form */ 112 $form = $event->data; 113 $html = $this->prepareLoginButtons(); 114 if (!$html) return; 115 116 // remove login form if single service is set 117 $singleService = $this->getConf('singleService'); 118 if ($singleService) { 119 do { 120 $form->removeElement(0); 121 } while ($form->elementCount() > 0); 122 } 123 124 $form->addFieldsetOpen($this->getLang('loginwith'))->addClass('plugin_oauth'); 125 $form->addHTML($html); 126 $form->addFieldsetClose(); 127 } 128 129 /** 130 * Create HTML for the various login buttons 131 * 132 * @return string the HTML 133 */ 134 protected function prepareLoginButtons() 135 { 136 $html = ''; 137 138 $validDomains = $this->hlp->getValidDomains(); 139 140 if (count($validDomains) > 0) { 141 $html .= '<p class="plugin-oauth-emailrestriction">' . sprintf( 142 $this->getLang('eMailRestricted'), 143 '<b>' . join(', ', $validDomains) . '</b>' 144 ) . '</p>'; 145 } 146 147 $html .= '<div>'; 148 foreach ($this->hlp->listServices() as $service) { 149 $html .= $service->loginButton(); 150 } 151 $html .= '</div>'; 152 153 return $html; 154 } 155 156 /** 157 * When singleservice is wanted, do not show login, but execute login right away 158 * 159 * @param Doku_Event $event 160 * @return bool 161 */ 162 public function handleDoLogin(Doku_Event $event) 163 { 164 global $ID; 165 166 if ($event->data != 'login') return true; 167 168 $singleService = $this->getConf('singleService'); 169 if (!$singleService) return true; 170 171 $enabledServices = $this->hlp->listServices(); 172 if (count($enabledServices) !== 1) { 173 msg($this->getLang('wrongConfig'), -1); 174 return false; 175 } 176 177 $service = array_shift($enabledServices); 178 179 $url = wl($ID, ['oauthlogin' => $service->getServiceID()], true, '&'); 180 send_redirect($url); 181 return true; // never reached 182 } 183 184} 185