1*c8525a21SAndreas Gohr<?php 2*c8525a21SAndreas Gohr 3*c8525a21SAndreas Gohruse dokuwiki\plugin\twofactor\Manager; 4*c8525a21SAndreas Gohr 5*c8525a21SAndreas Gohr/** 6*c8525a21SAndreas Gohr * DokuWiki Plugin twofactor (Action Component) 7*c8525a21SAndreas Gohr * 8*c8525a21SAndreas Gohr * This adds 2fa handling to the resendpwd action. It will interrupt the normal, first step of the 9*c8525a21SAndreas Gohr * flow and insert our own 2fa form, initialized with the user provided in the reset form. When the user 10*c8525a21SAndreas Gohr * has successfully authenticated, the normal flow will continue. All within the do?do=resendpwd action. 11*c8525a21SAndreas Gohr * 12*c8525a21SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 13*c8525a21SAndreas Gohr * @author Andreas Gohr <dokuwiki@cosmocode.de> 14*c8525a21SAndreas Gohr */ 15*c8525a21SAndreas Gohrclass action_plugin_twofactor_resendpwd extends \dokuwiki\Extension\ActionPlugin 16*c8525a21SAndreas Gohr{ 17*c8525a21SAndreas Gohr /** @inheritDoc */ 18*c8525a21SAndreas Gohr public function register(Doku_Event_Handler $controller) 19*c8525a21SAndreas Gohr { 20*c8525a21SAndreas Gohr $controller->register_hook( 21*c8525a21SAndreas Gohr 'ACTION_ACT_PREPROCESS', 22*c8525a21SAndreas Gohr 'BEFORE', 23*c8525a21SAndreas Gohr $this, 24*c8525a21SAndreas Gohr 'handleActionPreProcess', 25*c8525a21SAndreas Gohr null, 26*c8525a21SAndreas Gohr Manager::EVENT_PRIORITY - 1 27*c8525a21SAndreas Gohr ); 28*c8525a21SAndreas Gohr 29*c8525a21SAndreas Gohr $controller->register_hook( 30*c8525a21SAndreas Gohr 'TPL_ACT_UNKNOWN', 31*c8525a21SAndreas Gohr 'BEFORE', 32*c8525a21SAndreas Gohr $this, 33*c8525a21SAndreas Gohr 'handleTplActUnknown', 34*c8525a21SAndreas Gohr null, 35*c8525a21SAndreas Gohr Manager::EVENT_PRIORITY - 1 36*c8525a21SAndreas Gohr ); 37*c8525a21SAndreas Gohr } 38*c8525a21SAndreas Gohr 39*c8525a21SAndreas Gohr /** 40*c8525a21SAndreas Gohr * Event handler for ACTION_ACT_PREPROCESS 41*c8525a21SAndreas Gohr * 42*c8525a21SAndreas Gohr * @see https://www.dokuwiki.org/devel:events:ACTION_ACT_PREPROCESS 43*c8525a21SAndreas Gohr * @param Doku_Event $event Event object 44*c8525a21SAndreas Gohr * @param mixed $param optional parameter passed when event was registered 45*c8525a21SAndreas Gohr * @return void 46*c8525a21SAndreas Gohr */ 47*c8525a21SAndreas Gohr public function handleActionPreProcess(Doku_Event $event, $param) 48*c8525a21SAndreas Gohr { 49*c8525a21SAndreas Gohr if ($event->data !== 'resendpwd') return; 50*c8525a21SAndreas Gohr 51*c8525a21SAndreas Gohr global $INPUT; 52*c8525a21SAndreas Gohr if ($INPUT->has('pwauth')) return; // we're already in token phase, don't interrupt 53*c8525a21SAndreas Gohr if (!$INPUT->str('login')) return; // no user given yet, don't interrupt 54*c8525a21SAndreas Gohr 55*c8525a21SAndreas Gohr $user = $INPUT->str('login'); 56*c8525a21SAndreas Gohr $manager = Manager::getInstance(); 57*c8525a21SAndreas Gohr $manager->setUser($user); 58*c8525a21SAndreas Gohr 59*c8525a21SAndreas Gohr if (!$manager->isReady()) return; // no 2fa setup, don't interrupt 60*c8525a21SAndreas Gohr if (!count($manager->getUserProviders())) return; // no 2fa for this user, don't interrupt 61*c8525a21SAndreas Gohr 62*c8525a21SAndreas Gohr $code = $INPUT->post->str('2fa_code'); 63*c8525a21SAndreas Gohr $providerID = $INPUT->post->str('2fa_provider'); 64*c8525a21SAndreas Gohr if ($code && $manager->verifyCode($code, $providerID)) { 65*c8525a21SAndreas Gohr // all is good, don't interrupt 66*c8525a21SAndreas Gohr Manager::destroyInstance(); // remove our instance so login.php can create a new one 67*c8525a21SAndreas Gohr return; 68*c8525a21SAndreas Gohr } 69*c8525a21SAndreas Gohr 70*c8525a21SAndreas Gohr // we're still here, so we need to interrupt 71*c8525a21SAndreas Gohr $event->preventDefault(); 72*c8525a21SAndreas Gohr $event->stopPropagation(); 73*c8525a21SAndreas Gohr 74*c8525a21SAndreas Gohr // next, we will overwrite the resendpwd form with our own in TPL_ACT_UNKNOWN 75*c8525a21SAndreas Gohr } 76*c8525a21SAndreas Gohr 77*c8525a21SAndreas Gohr /** 78*c8525a21SAndreas Gohr * Event handler for TPL_ACT_UNKNOWN 79*c8525a21SAndreas Gohr * 80*c8525a21SAndreas Gohr * This is executed only when we prevented the default action in handleActionPreProcess() 81*c8525a21SAndreas Gohr * 82*c8525a21SAndreas Gohr * @see https://www.dokuwiki.org/devel:events:TPL_ACT_UNKNOWN 83*c8525a21SAndreas Gohr * @param Doku_Event $event Event object 84*c8525a21SAndreas Gohr * @param mixed $param optional parameter passed when event was registered 85*c8525a21SAndreas Gohr * @return void 86*c8525a21SAndreas Gohr */ 87*c8525a21SAndreas Gohr public function handleTplActUnknown(Doku_Event $event, $param) 88*c8525a21SAndreas Gohr { 89*c8525a21SAndreas Gohr if ($event->data !== 'resendpwd') return; 90*c8525a21SAndreas Gohr $event->stopPropagation(); 91*c8525a21SAndreas Gohr $event->preventDefault(); 92*c8525a21SAndreas Gohr 93*c8525a21SAndreas Gohr global $INPUT; 94*c8525a21SAndreas Gohr 95*c8525a21SAndreas Gohr $providerID = $INPUT->post->str('2fa_provider'); 96*c8525a21SAndreas Gohr 97*c8525a21SAndreas Gohr $manager = Manager::getInstance(); 98*c8525a21SAndreas Gohr $form = $manager->getCodeForm($providerID); 99*c8525a21SAndreas Gohr 100*c8525a21SAndreas Gohr // overwrite form defaults, to redo the resendpwd action but with the code supplied 101*c8525a21SAndreas Gohr $form->setHiddenField('do', 'resendpwd'); 102*c8525a21SAndreas Gohr $form->setHiddenField('login', $INPUT->str('login')); 103*c8525a21SAndreas Gohr $form->setHiddenField('save', 1); 104*c8525a21SAndreas Gohr 105*c8525a21SAndreas Gohr 106*c8525a21SAndreas Gohr echo '<div class="plugin_twofactor_login">'; 107*c8525a21SAndreas Gohr echo inlineSVG(__DIR__ . '/../admin.svg'); 108*c8525a21SAndreas Gohr echo $this->locale_xhtml('resendpwd'); 109*c8525a21SAndreas Gohr echo $form->toHTML(); 110*c8525a21SAndreas Gohr echo '</div>'; 111*c8525a21SAndreas Gohr } 112*c8525a21SAndreas Gohr} 113*c8525a21SAndreas Gohr 114