1<?php 2 3use OAuth\Common\Http\Exception\TokenResponseException; 4 5/** 6 * DokuWiki Plugin oauth (Action Component) 7 * 8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 9 * @author Andreas Gohr <andi@splitbrain.org> 10 */ 11class action_plugin_oauth_login extends DokuWiki_Action_Plugin 12{ 13 /** @var helper_plugin_oauth */ 14 protected $hlp; 15 16 /** 17 * Constructor 18 * 19 * Initializes the helper 20 */ 21 public function __construct() 22 { 23 $this->hlp = plugin_load('helper', 'oauth'); 24 } 25 26 /** 27 * Registers a callback function for a given event 28 * 29 * @param Doku_Event_Handler $controller DokuWiki's event controller object 30 * @return void 31 */ 32 public function register(Doku_Event_Handler $controller) 33 { 34 global $conf; 35 if ($conf['authtype'] != 'oauth') return; 36 37 $conf['profileconfirm'] = false; // password confirmation doesn't work with oauth only users 38 39 $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handleStart'); 40 $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handleLoginform'); 41 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleDoLogin'); 42 } 43 44 /** 45 * Start an oAuth login or restore environment after successful login 46 * 47 * @param Doku_Event $event 48 * @return void 49 */ 50 public function handleStart(Doku_Event $event) 51 { 52 global $INPUT; 53 54 // login has been done, but there's environment to be restored 55 if (isset($_SESSION[DOKU_COOKIE]['oauth-done']['do']) || !empty($_SESSION[DOKU_COOKIE]['oauth-done']['rev'])) { 56 $this->restoreSessionEnvironment(); 57 return; 58 } 59 60 // see if a login needs to be started 61 $servicename = $INPUT->str('oauthlogin'); 62 if ($servicename) $this->startOAuthLogin($servicename); 63 } 64 65 /** 66 * Add the oAuth login links 67 * 68 * @param Doku_Event $event event object by reference 69 * @return void 70 */ 71 public function handleLoginform(Doku_Event $event) 72 { 73 /** @var Doku_Form $form */ 74 $form = $event->data; 75 $html = ''; 76 77 $validDomains = $this->hlp->getValidDomains(); 78 79 if (count($validDomains) > 0) { 80 $html .= sprintf($this->getLang('eMailRestricted'), join(', ', $validDomains)); 81 } 82 83 foreach ($this->hlp->listServices() as $service) { 84 $html .= $service->loginButton(); 85 } 86 if (!$html) return; 87 88 $form->_content[] = form_openfieldset( 89 [ 90 '_legend' => $this->getLang('loginwith'), 91 'class' => 'plugin_oauth', 92 ] 93 ); 94 $form->_content[] = $html; 95 $form->_content[] = form_closefieldset(); 96 } 97 98 /** 99 * When singleservice is wanted, do not show login, but execute login right away 100 * 101 * @param Doku_Event $event 102 * @return bool 103 */ 104 public function handleDoLogin(Doku_Event $event) 105 { 106 global $ID; 107 108 if ($event->data != 'login') return true; 109 110 $singleService = $this->getConf('singleService'); 111 if (!$singleService) return true; 112 113 $enabledServices = $this->hlp->listServices(); 114 if (count($enabledServices) !== 1) { 115 msg($this->getLang('wrongConfig'), -1); 116 return false; 117 } 118 119 $service = array_shift($enabledServices); 120 121 $url = wl($ID, ['oauthlogin' => $service->getServiceID()], true, '&'); 122 send_redirect($url); 123 return true; // never reached 124 } 125 126 /** 127 * start the oauth login 128 * 129 * This will redirect to the external service and stop processing in this request. 130 * The second part of the login will happen in auth 131 * 132 * @see auth_plugin_oauth 133 */ 134 protected function startOAuthLogin($servicename) 135 { 136 global $ID; 137 $service = $this->hlp->loadService($servicename); 138 if (is_null($service)) return; 139 140 // remember service in session 141 session_start(); 142 $_SESSION[DOKU_COOKIE]['oauth-inprogress']['service'] = $servicename; 143 $_SESSION[DOKU_COOKIE]['oauth-inprogress']['id'] = $ID; 144 session_write_close(); 145 146 try { 147 $service->login(); // redirects 148 } catch (TokenResponseException $e) { 149 $this->hlp->showException($e, 'login failed'); 150 } 151 } 152 153 /** 154 * Restore the request environment that had been set before the oauth shuffle 155 */ 156 protected function restoreSessionEnvironment() 157 { 158 global $INPUT, $ACT, $TEXT, $PRE, $SUF, $SUM, $RANGE, $DATE_AT, $REV; 159 $ACT = $_SESSION[DOKU_COOKIE]['oauth-done']['do']; 160 $_REQUEST = $_SESSION[DOKU_COOKIE]['oauth-done']['$_REQUEST']; 161 162 $REV = $INPUT->int('rev'); 163 $DATE_AT = $INPUT->str('at'); 164 $RANGE = $INPUT->str('range'); 165 if ($INPUT->post->has('wikitext')) { 166 $TEXT = cleanText($INPUT->post->str('wikitext')); 167 } 168 $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1)); 169 $SUF = cleanText($INPUT->post->str('suffix')); 170 $SUM = $INPUT->post->str('summary'); 171 172 unset($_SESSION[DOKU_COOKIE]['oauth-done']); 173 } 174} 175