1<?php 2 3use dokuwiki\Form\Form; 4use dokuwiki\plugin\oauth\SessionManager; 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 // login has been done, but there's environment to be restored 61 // TODO when is this the case? 62 $sessionManager = SessionManager::getInstance(); 63 if ($sessionManager->getDo() || $sessionManager->getRev()) { 64 $this->restoreSessionEnvironment(); 65 return; 66 } 67 68 // see if a login needs to be started 69 $servicename = $INPUT->str('oauthlogin'); 70 if ($servicename) $this->startOAuthLogin($servicename); 71 } 72 73 /** 74 * Add the oAuth login links to login form 75 * 76 * @param Doku_Event $event event object by reference 77 * @return void 78 * @deprecated can be removed in the future 79 */ 80 public function handleOldLoginForm(Doku_Event $event) 81 { 82 /** @var Doku_Form $form */ 83 $form = $event->data; 84 $html = $this->prepareLoginButtons(); 85 if (!$html) return; 86 87 $form->_content[] = form_openfieldset( 88 [ 89 '_legend' => $this->getLang('loginwith'), 90 'class' => 'plugin_oauth', 91 ] 92 ); 93 $form->_content[] = $html; 94 $form->_content[] = form_closefieldset(); 95 } 96 97 /** 98 * Add the oAuth login links to login form 99 * 100 * @param Doku_Event $event event object by reference 101 * @return void 102 * @deprecated can be removed in the future 103 */ 104 public function handleLoginForm(Doku_Event $event) 105 { 106 /** @var Form $form */ 107 $form = $event->data; 108 $html = $this->prepareLoginButtons(); 109 if (!$html) return; 110 111 $form->addFieldsetOpen($this->getLang('loginwith'))->addClass('plugin_oauth'); 112 $form->addHTML($html); 113 $form->addFieldsetClose(); 114 } 115 116 /** 117 * Create HTML for the various login buttons 118 * 119 * @return string the HTML 120 */ 121 protected function prepareLoginButtons() 122 { 123 $html = ''; 124 125 $validDomains = $this->hlp->getValidDomains(); 126 127 if (count($validDomains) > 0) { 128 $html .= '<p class="plugin-oauth-emailrestriction">' . sprintf( 129 $this->getLang('eMailRestricted'), 130 '<b>' . join(', ', $validDomains) . '</b>' 131 ) . '</p>'; 132 } 133 134 foreach ($this->hlp->listServices() as $service) { 135 $html .= $service->loginButton(); 136 } 137 138 return $html; 139 } 140 141 /** 142 * When singleservice is wanted, do not show login, but execute login right away 143 * 144 * @param Doku_Event $event 145 * @return bool 146 */ 147 public function handleDoLogin(Doku_Event $event) 148 { 149 global $ID; 150 151 if ($event->data != 'login') return true; 152 153 $singleService = $this->getConf('singleService'); 154 if (!$singleService) return true; 155 156 $enabledServices = $this->hlp->listServices(); 157 if (count($enabledServices) !== 1) { 158 msg($this->getLang('wrongConfig'), -1); 159 return false; 160 } 161 162 $service = array_shift($enabledServices); 163 164 $url = wl($ID, ['oauthlogin' => $service->getServiceID()], true, '&'); 165 send_redirect($url); 166 return true; // never reached 167 } 168 169 /** 170 * start the oauth login 171 * 172 * This will redirect to the external service and stop processing in this request. 173 * The second part of the login will happen in auth 174 * 175 * @see auth_plugin_oauth 176 */ 177 protected function startOAuthLogin($servicename) 178 { 179 global $ID; 180// $service = $this->hlp->loadService($servicename); 181// if (is_null($service)) return; 182// 183// // remember service in session 184// $sessionManager = SessionManager::getInstance(); 185// $sessionManager->setServiceName($servicename); 186// $sessionManager->setPid($ID); 187// $sessionManager->saveState(); 188 189 try { 190 $om = new \dokuwiki\plugin\oauth\OAuthManager(); 191 $om->startFlow($servicename); 192 } catch (TokenResponseException|Exception $e) { 193 $this->hlp->showException($e, 'login failed'); 194 } 195 } 196 197 /** 198 * Restore the request environment that had been set before the oauth shuffle 199 * @todo this should be handled by the session manager, if we really need it 200 */ 201 protected function restoreSessionEnvironment() 202 { 203 global $INPUT, $ACT, $TEXT, $PRE, $SUF, $SUM, $RANGE, $DATE_AT, $REV; 204 205 $sessionManager = SessionManager::getInstance(); 206 $ACT = $sessionManager->getDo(); 207 $_REQUEST = $sessionManager->getRequest(); 208 209 $REV = $INPUT->int('rev'); 210 $DATE_AT = $INPUT->str('at'); 211 $RANGE = $INPUT->str('range'); 212 if ($INPUT->post->has('wikitext')) { 213 $TEXT = cleanText($INPUT->post->str('wikitext')); 214 } 215 $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1)); 216 $SUF = cleanText($INPUT->post->str('suffix')); 217 $SUM = $INPUT->post->str('summary'); 218 219 $sessionManager->setDo(''); 220 $sessionManager->setRequest([]); 221 $sessionManager->saveState(); 222 } 223} 224