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