xref: /plugin/oauth/action/login.php (revision 6f3a59e8e507433aa78067cb8d1475ba77fa05f7)
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 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author  Andreas Gohr <andi@splitbrain.org>
12 */
13class action_plugin_oauth_login extends DokuWiki_Action_Plugin
14{
15    /** @var helper_plugin_oauth */
16    protected $hlp;
17
18    /**
19     * Constructor
20     *
21     * Initializes the helper
22     */
23    public function __construct()
24    {
25        $this->hlp = plugin_load('helper', 'oauth');
26    }
27
28    /**
29     * Registers a callback function for a given event
30     *
31     * @param Doku_Event_Handler $controller DokuWiki's event controller object
32     * @return void
33     */
34    public function register(Doku_Event_Handler $controller)
35    {
36        global $conf;
37        if ($conf['authtype'] != 'oauth') return;
38
39        $conf['profileconfirm'] = false; // password confirmation doesn't work with oauth only users
40
41        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'handleStart');
42        $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handleOldLoginForm'); // @deprecated
43        $controller->register_hook('FORM_LOGIN_OUTPUT', 'BEFORE', $this, 'handleLoginForm');
44        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleDoLogin');
45    }
46
47    /**
48     * Start an oAuth login or restore  environment after successful login
49     *
50     * @param Doku_Event $event
51     * @return void
52     */
53    public function handleStart(Doku_Event $event)
54    {
55        global $INPUT;
56
57        // login has been done, but there's environment to be restored
58        // TODO when is this the case?
59        $sessionManager = SessionManager::getInstance();
60        if ($sessionManager->getDo() || $sessionManager->getRev()) {
61            $this->restoreSessionEnvironment();
62            return;
63        }
64
65        // see if a login needs to be started
66        $servicename = $INPUT->str('oauthlogin');
67        if ($servicename) $this->startOAuthLogin($servicename);
68    }
69
70    /**
71     * Add the oAuth login links to login form
72     *
73     * @param Doku_Event $event event object by reference
74     * @deprecated can be removed in the future
75     * @return void
76     */
77    public function handleOldLoginForm(Doku_Event $event)
78    {
79        /** @var Doku_Form $form */
80        $form = $event->data;
81        $html = $this->prepareLoginButtons();
82        if (!$html) return;
83
84        $form->_content[] = form_openfieldset(
85            [
86                '_legend' => $this->getLang('loginwith'),
87                'class' => 'plugin_oauth',
88            ]
89        );
90        $form->_content[] = $html;
91        $form->_content[] = form_closefieldset();
92    }
93
94
95    /**
96     * Add the oAuth login links to login form
97     *
98     * @param Doku_Event $event event object by reference
99     * @deprecated can be removed in the future
100     * @return void
101     */
102    public function handleLoginForm(Doku_Event $event)
103    {
104        /** @var Form $form */
105        $form = $event->data;
106        $html = $this->prepareLoginButtons();
107        if (!$html) return;
108
109        $form->addFieldsetOpen($this->getLang('loginwith'))->addClass('plugin_oauth');
110        $form->addHTML($html);
111        $form->addFieldsetClose();
112    }
113
114    /**
115     * Create HTML for the various login buttons
116     *
117     * @return string the HTML
118     */
119    protected function prepareLoginButtons() {
120        $html = '';
121
122        $validDomains = $this->hlp->getValidDomains();
123
124        if (count($validDomains) > 0) {
125            $html .= '<p class="plugin-oauth-emailrestriction">' . sprintf(
126                    $this->getLang('eMailRestricted'),
127                    '<b>' . join(', ', $validDomains) . '</b>'
128                ) . '</p>';
129        }
130
131        foreach ($this->hlp->listServices() as $service) {
132            $html .= $service->loginButton();
133        }
134
135        return $html;
136    }
137
138    /**
139     * When singleservice is wanted, do not show login, but execute login right away
140     *
141     * @param Doku_Event $event
142     * @return bool
143     */
144    public function handleDoLogin(Doku_Event $event)
145    {
146        global $ID;
147
148        if ($event->data != 'login') return true;
149
150        $singleService = $this->getConf('singleService');
151        if (!$singleService) return true;
152
153        $enabledServices = $this->hlp->listServices();
154        if (count($enabledServices) !== 1) {
155            msg($this->getLang('wrongConfig'), -1);
156            return false;
157        }
158
159        $service = array_shift($enabledServices);
160
161        $url = wl($ID, ['oauthlogin' => $service->getServiceID()], true, '&');
162        send_redirect($url);
163        return true; // never reached
164    }
165
166    /**
167     * start the oauth login
168     *
169     * This will redirect to the external service and stop processing in this request.
170     * The second part of the login will happen in auth
171     *
172     * @see auth_plugin_oauth
173     */
174    protected function startOAuthLogin($servicename)
175    {
176        global $ID;
177        $service = $this->hlp->loadService($servicename);
178        if (is_null($service)) return;
179
180        // remember service in session
181        $sessionManager = SessionManager::getInstance();
182        $sessionManager->setServiceName($servicename);
183        $sessionManager->setPid($ID);
184        $sessionManager->saveState();
185
186        try {
187            $service->login(); // redirects
188        } catch (TokenResponseException $e) {
189            $this->hlp->showException($e, 'login failed');
190        }
191    }
192
193    /**
194     * Restore the request environment that had been set before the oauth shuffle
195     */
196    protected function restoreSessionEnvironment()
197    {
198        global $INPUT, $ACT, $TEXT, $PRE, $SUF, $SUM, $RANGE, $DATE_AT, $REV;
199
200        $sessionManager = SessionManager::getInstance();
201        $ACT = $sessionManager->getDo();
202        $_REQUEST = $sessionManager->getRequest();
203
204        $REV = $INPUT->int('rev');
205        $DATE_AT = $INPUT->str('at');
206        $RANGE = $INPUT->str('range');
207        if ($INPUT->post->has('wikitext')) {
208            $TEXT = cleanText($INPUT->post->str('wikitext'));
209        }
210        $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
211        $SUF = cleanText($INPUT->post->str('suffix'));
212        $SUM = $INPUT->post->str('summary');
213
214        $sessionManager->setDo('');
215        $sessionManager->setRequest([]);
216        $sessionManager->saveState();
217    }
218}
219