xref: /plugin/oauth/action/login.php (revision 290e9b1f10bf4135eb82799dc58da0055064d995)
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