xref: /plugin/oauth/auth.php (revision e32c360756c56568294afdbe74c9557dba7838d0)
180852c15SAndreas Gohr<?php
280852c15SAndreas Gohr/**
380852c15SAndreas Gohr * DokuWiki Plugin oauth (Auth Component)
480852c15SAndreas Gohr *
580852c15SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
680852c15SAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
780852c15SAndreas Gohr */
880852c15SAndreas Gohr
980852c15SAndreas Gohr// must be run within Dokuwiki
1080852c15SAndreas Gohrif(!defined('DOKU_INC')) die();
1180852c15SAndreas Gohr
12f10e09e2SAndreas Gohrclass auth_plugin_oauth extends auth_plugin_authplain {
1380852c15SAndreas Gohr
14f866280eSAndreas Gohr    /**
15f866280eSAndreas Gohr     * Constructor
16f866280eSAndreas Gohr     *
17f866280eSAndreas Gohr     * Sets capabilities.
18f866280eSAndreas Gohr     */
1980852c15SAndreas Gohr    public function __construct() {
20f10e09e2SAndreas Gohr        parent::__construct();
2180852c15SAndreas Gohr
22f10e09e2SAndreas Gohr        $this->cando['external'] = true;
2380852c15SAndreas Gohr    }
2480852c15SAndreas Gohr
25f866280eSAndreas Gohr    /**
26f866280eSAndreas Gohr     * Handle the login
27f866280eSAndreas Gohr     *
28f866280eSAndreas Gohr     * This either trusts the session data (if any), processes the second oAuth step or simply
29f866280eSAndreas Gohr     * executes a normal plugin against local users.
30f866280eSAndreas Gohr     *
31f866280eSAndreas Gohr     * @param string $user
32f866280eSAndreas Gohr     * @param string $pass
33f866280eSAndreas Gohr     * @param bool   $sticky
34f866280eSAndreas Gohr     * @return bool
35f866280eSAndreas Gohr     */
36f10e09e2SAndreas Gohr    function trustExternal($user, $pass, $sticky = false) {
37a7a8f46aSAndreas Gohr        global $INPUT;
38a7a8f46aSAndreas Gohr        global $conf;
39a7a8f46aSAndreas Gohr        global $USERINFO;
4080852c15SAndreas Gohr
41a7a8f46aSAndreas Gohr        $servicename = $INPUT->str('oa');
4280852c15SAndreas Gohr
43a7a8f46aSAndreas Gohr        // check session for existing oAuth login data
44a7a8f46aSAndreas Gohr        $session = $_SESSION[DOKU_COOKIE]['auth'];
45a7a8f46aSAndreas Gohr        if(!$servicename && isset($session['oauth'])) {
46a7a8f46aSAndreas Gohr            $servicename = $session['oauth'];
47a7a8f46aSAndreas Gohr            // check if session data is still considered valid
48a7a8f46aSAndreas Gohr            if(($session['time'] >= time() - $conf['auth_security_timeout']) &&
49f866280eSAndreas Gohr                ($session['buid'] == auth_browseruid())
50f866280eSAndreas Gohr            ) {
5180852c15SAndreas Gohr
52a7a8f46aSAndreas Gohr                $_SERVER['REMOTE_USER'] = $session['user'];
53a7a8f46aSAndreas Gohr                $USERINFO               = $session['info'];
5480852c15SAndreas Gohr                return true;
55f10e09e2SAndreas Gohr            }
5680852c15SAndreas Gohr        }
5780852c15SAndreas Gohr
58a7a8f46aSAndreas Gohr        // either we're in oauth login or a previous log needs to be rechecked
59a7a8f46aSAndreas Gohr        if($servicename) {
60a7a8f46aSAndreas Gohr            /** @var helper_plugin_oauth $hlp */
61a7a8f46aSAndreas Gohr            $hlp     = plugin_load('helper', 'oauth');
62a7a8f46aSAndreas Gohr            $service = $hlp->loadService($servicename);
63a7a8f46aSAndreas Gohr            if(is_null($service)) return false;
64a7a8f46aSAndreas Gohr
65a7a8f46aSAndreas Gohr            // get the token
66a7a8f46aSAndreas Gohr            if($service->checkToken()) {
67a7a8f46aSAndreas Gohr                $uinfo = $service->getUser();
68f866280eSAndreas Gohr
69f866280eSAndreas Gohr                // see if the user is known already
70f866280eSAndreas Gohr                $user = $this->getUserByEmail($uinfo['mail']);
71f866280eSAndreas Gohr                if($user) {
72f866280eSAndreas Gohr                    $sinfo         = $this->getUserData($user);
73f866280eSAndreas Gohr                    $uinfo['user'] = $user;
74f866280eSAndreas Gohr                    $uinfo['name'] = $sinfo['name'];
75f866280eSAndreas Gohr                    $uinfo['grps'] = array_merge((array) $uinfo['grps'], $sinfo['grps']);
76f866280eSAndreas Gohr                } else {
77f866280eSAndreas Gohr                    // new user, create him - making sure the login is unique by adding a number if needed
78f866280eSAndreas Gohr                    $user  = $uinfo['user'];
79f866280eSAndreas Gohr                    $count = '';
80f866280eSAndreas Gohr                    while($this->getUserData($user.$count)) {
81f866280eSAndreas Gohr                        if($count) {
82f866280eSAndreas Gohr                            $count++;
83f866280eSAndreas Gohr                        } else {
84f866280eSAndreas Gohr                            $count = 1;
85f866280eSAndreas Gohr                        }
86f866280eSAndreas Gohr                    }
87f866280eSAndreas Gohr                    $user          = $user.$count;
88f866280eSAndreas Gohr                    $uinfo['user'] = $user;
89f866280eSAndreas Gohr                    $uinfo['grps'] = (array) $uinfo['grps'];
90f866280eSAndreas Gohr                    $uinfo['grps'][] = $conf['defaultgroup'];
91f866280eSAndreas Gohr
92f866280eSAndreas Gohr                    $this->createUser($user, auth_pwgen($user), $uinfo['name'], $uinfo['mail'], $uinfo['grps']);
93f866280eSAndreas Gohr                }
94f866280eSAndreas Gohr
95f866280eSAndreas Gohr                // set user session
96a7a8f46aSAndreas Gohr                $this->setUserSession($uinfo, $servicename);
97a7a8f46aSAndreas Gohr                return true;
98a7a8f46aSAndreas Gohr            }
99a7a8f46aSAndreas Gohr
100a7a8f46aSAndreas Gohr            return false; // something went wrong during oAuth login
10180852c15SAndreas Gohr        }
10280852c15SAndreas Gohr
103a7a8f46aSAndreas Gohr        // do the "normal" plain auth login via form
104a7a8f46aSAndreas Gohr        return auth_login($user, $pass, $sticky);
105a7a8f46aSAndreas Gohr    }
10680852c15SAndreas Gohr
107a7a8f46aSAndreas Gohr    /**
108a7a8f46aSAndreas Gohr     * @param array  $data
109a7a8f46aSAndreas Gohr     * @param string $service
110a7a8f46aSAndreas Gohr     */
111a7a8f46aSAndreas Gohr    protected function setUserSession($data, $service) {
112a7a8f46aSAndreas Gohr        global $USERINFO;
113a7a8f46aSAndreas Gohr        global $conf;
114a7a8f46aSAndreas Gohr
115a7a8f46aSAndreas Gohr        // set up groups
116a7a8f46aSAndreas Gohr        if(!is_array($data['grps'])) {
117a7a8f46aSAndreas Gohr            $data['grps'] = array();
118a7a8f46aSAndreas Gohr        }
119a7a8f46aSAndreas Gohr        $data['grps'][] = $this->cleanGroup($service);
120f866280eSAndreas Gohr        $data['grps']   = array_unique($data['grps']);
12180852c15SAndreas Gohr
122f10e09e2SAndreas Gohr        $USERINFO                               = $data;
123f10e09e2SAndreas Gohr        $_SERVER['REMOTE_USER']                 = $data['user'];
124f10e09e2SAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['user']  = $data['user'];
125f10e09e2SAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['pass']  = $data['pass'];
126f10e09e2SAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['info']  = $USERINFO;
127a7a8f46aSAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['buid']  = auth_browseruid();
128a7a8f46aSAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['time']  = time();
129a7a8f46aSAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['oauth'] = $service;
13080852c15SAndreas Gohr    }
13180852c15SAndreas Gohr
132f866280eSAndreas Gohr    /**
133*e32c3607SAndreas Gohr     * Unset additional stuff in session on logout
134*e32c3607SAndreas Gohr     */
135*e32c3607SAndreas Gohr    public function logOff() {
136*e32c3607SAndreas Gohr        parent::logOff();
137*e32c3607SAndreas Gohr
138*e32c3607SAndreas Gohr        if(isset($_SESSION[DOKU_COOKIE]['auth']['buid'])) {
139*e32c3607SAndreas Gohr            unset($_SESSION[DOKU_COOKIE]['auth']['buid']);
140*e32c3607SAndreas Gohr        }
141*e32c3607SAndreas Gohr        if(isset($_SESSION[DOKU_COOKIE]['auth']['time'])) {
142*e32c3607SAndreas Gohr            unset($_SESSION[DOKU_COOKIE]['auth']['time']);
143*e32c3607SAndreas Gohr        }
144*e32c3607SAndreas Gohr        if(isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) {
145*e32c3607SAndreas Gohr            unset($_SESSION[DOKU_COOKIE]['auth']['oauth']);
146*e32c3607SAndreas Gohr        }
147*e32c3607SAndreas Gohr    }
148*e32c3607SAndreas Gohr
149*e32c3607SAndreas Gohr    /**
150f866280eSAndreas Gohr     * Find a user by his email address
151f866280eSAndreas Gohr     *
152f866280eSAndreas Gohr     * @param $mail
153f866280eSAndreas Gohr     * @return bool|string
154f866280eSAndreas Gohr     */
15538378fbbSAndreas Gohr    protected function getUserByEmail($mail) {
156f866280eSAndreas Gohr        if($this->users === null) $this->_loadUserData();
15738378fbbSAndreas Gohr        $mail = strtolower($mail);
158f866280eSAndreas Gohr
159f866280eSAndreas Gohr        foreach($this->users as $user => $uinfo) {
160f866280eSAndreas Gohr            if(strtolower($uinfo['mail']) == $mail) return $user;
16138378fbbSAndreas Gohr        }
16238378fbbSAndreas Gohr
163f866280eSAndreas Gohr        return false;
164f866280eSAndreas Gohr    }
16538378fbbSAndreas Gohr
166f866280eSAndreas Gohr    /**
167f866280eSAndreas Gohr     * Enhance function to check aainst duplicate emails
168f866280eSAndreas Gohr     *
169f866280eSAndreas Gohr     * @param string $user
170f866280eSAndreas Gohr     * @param string $pwd
171f866280eSAndreas Gohr     * @param string $name
172f866280eSAndreas Gohr     * @param string $mail
173f866280eSAndreas Gohr     * @param null   $grps
174f866280eSAndreas Gohr     * @return bool|null|string
175f866280eSAndreas Gohr     */
176f866280eSAndreas Gohr    public function createUser($user, $pwd, $name, $mail, $grps = null) {
177f866280eSAndreas Gohr        if($this->getUserByEmail($mail)) {
178f866280eSAndreas Gohr            msg($this->getLang('emailduplicate'), -1);
179f866280eSAndreas Gohr            return false;
180f866280eSAndreas Gohr        }
181f866280eSAndreas Gohr
18238378fbbSAndreas Gohr        return parent::createUser($user, $pwd, $name, $mail, $grps);
18338378fbbSAndreas Gohr    }
18438378fbbSAndreas Gohr
185f866280eSAndreas Gohr    /**
186f866280eSAndreas Gohr     * Enhance function to check aainst duplicate emails
187f866280eSAndreas Gohr     *
188f866280eSAndreas Gohr     * @param string $user
189f866280eSAndreas Gohr     * @param array  $changes
190f866280eSAndreas Gohr     * @return bool
191f866280eSAndreas Gohr     */
19238378fbbSAndreas Gohr    public function modifyUser($user, $changes) {
193f866280eSAndreas Gohr        if(isset($changes['mail']) && $this->getUserByEmail($changes['mail'])) {
194f866280eSAndreas Gohr            msg($this->getLang('emailduplicate'), -1);
195f866280eSAndreas Gohr            return false;
196f866280eSAndreas Gohr        }
19738378fbbSAndreas Gohr
19838378fbbSAndreas Gohr        return parent::modifyUser($user, $changes);
19938378fbbSAndreas Gohr    }
20038378fbbSAndreas Gohr
20180852c15SAndreas Gohr}
20280852c15SAndreas Gohr
20380852c15SAndreas Gohr// vim:ts=4:sw=4:et: