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