xref: /plugin/oauth/auth.php (revision 1025aad7dc1e04d3a1f62d698bf90b5fff173c02)
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
69*1025aad7SAndreas Gohr                $uinfo['user'] = $this->cleanUser((string) $uinfo['user']);
70*1025aad7SAndreas Gohr                if(!$uinfo['name']) $uinfo['name'] = $uinfo['user'];
71*1025aad7SAndreas Gohr
72*1025aad7SAndreas Gohr                if(!$uinfo['user'] || !$uinfo['mail']) {
73*1025aad7SAndreas Gohr                    msg("$servicename did not provide the needed user info. Can't log you in", -1);
74*1025aad7SAndreas Gohr                    return false;
75*1025aad7SAndreas Gohr                }
76*1025aad7SAndreas Gohr
77f866280eSAndreas Gohr                // see if the user is known already
78f866280eSAndreas Gohr                $user = $this->getUserByEmail($uinfo['mail']);
79f866280eSAndreas Gohr                if($user) {
80f866280eSAndreas Gohr                    $sinfo         = $this->getUserData($user);
81f866280eSAndreas Gohr                    $uinfo['user'] = $user;
82f866280eSAndreas Gohr                    $uinfo['name'] = $sinfo['name'];
83f866280eSAndreas Gohr                    $uinfo['grps'] = array_merge((array) $uinfo['grps'], $sinfo['grps']);
84f866280eSAndreas Gohr                } else {
85f866280eSAndreas Gohr                    // new user, create him - making sure the login is unique by adding a number if needed
86f866280eSAndreas Gohr                    $user  = $uinfo['user'];
87f866280eSAndreas Gohr                    $count = '';
88f866280eSAndreas Gohr                    while($this->getUserData($user.$count)) {
89f866280eSAndreas Gohr                        if($count) {
90f866280eSAndreas Gohr                            $count++;
91f866280eSAndreas Gohr                        } else {
92f866280eSAndreas Gohr                            $count = 1;
93f866280eSAndreas Gohr                        }
94f866280eSAndreas Gohr                    }
95f866280eSAndreas Gohr                    $user            = $user.$count;
96f866280eSAndreas Gohr                    $uinfo['user']   = $user;
97f866280eSAndreas Gohr                    $uinfo['grps']   = (array) $uinfo['grps'];
98f866280eSAndreas Gohr                    $uinfo['grps'][] = $conf['defaultgroup'];
99f866280eSAndreas Gohr
100f866280eSAndreas Gohr                    $this->createUser($user, auth_pwgen($user), $uinfo['name'], $uinfo['mail'], $uinfo['grps']);
101f866280eSAndreas Gohr                }
102f866280eSAndreas Gohr
103f866280eSAndreas Gohr                // set user session
104a7a8f46aSAndreas Gohr                $this->setUserSession($uinfo, $servicename);
105a7a8f46aSAndreas Gohr                return true;
106a7a8f46aSAndreas Gohr            }
107a7a8f46aSAndreas Gohr
108a7a8f46aSAndreas Gohr            return false; // something went wrong during oAuth login
10980852c15SAndreas Gohr        }
11080852c15SAndreas Gohr
111a7a8f46aSAndreas Gohr        // do the "normal" plain auth login via form
112a7a8f46aSAndreas Gohr        return auth_login($user, $pass, $sticky);
113a7a8f46aSAndreas Gohr    }
11480852c15SAndreas Gohr
115a7a8f46aSAndreas Gohr    /**
116a7a8f46aSAndreas Gohr     * @param array  $data
117a7a8f46aSAndreas Gohr     * @param string $service
118a7a8f46aSAndreas Gohr     */
119a7a8f46aSAndreas Gohr    protected function setUserSession($data, $service) {
120a7a8f46aSAndreas Gohr        global $USERINFO;
121a7a8f46aSAndreas Gohr        global $conf;
122a7a8f46aSAndreas Gohr
123a7a8f46aSAndreas Gohr        // set up groups
124a7a8f46aSAndreas Gohr        if(!is_array($data['grps'])) {
125a7a8f46aSAndreas Gohr            $data['grps'] = array();
126a7a8f46aSAndreas Gohr        }
127a7a8f46aSAndreas Gohr        $data['grps'][] = $this->cleanGroup($service);
128f866280eSAndreas Gohr        $data['grps']   = array_unique($data['grps']);
12980852c15SAndreas Gohr
130f10e09e2SAndreas Gohr        $USERINFO                               = $data;
131f10e09e2SAndreas Gohr        $_SERVER['REMOTE_USER']                 = $data['user'];
132f10e09e2SAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['user']  = $data['user'];
133f10e09e2SAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['pass']  = $data['pass'];
134f10e09e2SAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['info']  = $USERINFO;
135a7a8f46aSAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['buid']  = auth_browseruid();
136a7a8f46aSAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['time']  = time();
137a7a8f46aSAndreas Gohr        $_SESSION[DOKU_COOKIE]['auth']['oauth'] = $service;
13880852c15SAndreas Gohr    }
13980852c15SAndreas Gohr
140f866280eSAndreas Gohr    /**
141e32c3607SAndreas Gohr     * Unset additional stuff in session on logout
142e32c3607SAndreas Gohr     */
143e32c3607SAndreas Gohr    public function logOff() {
144e32c3607SAndreas Gohr        parent::logOff();
145e32c3607SAndreas Gohr
146e32c3607SAndreas Gohr        if(isset($_SESSION[DOKU_COOKIE]['auth']['buid'])) {
147e32c3607SAndreas Gohr            unset($_SESSION[DOKU_COOKIE]['auth']['buid']);
148e32c3607SAndreas Gohr        }
149e32c3607SAndreas Gohr        if(isset($_SESSION[DOKU_COOKIE]['auth']['time'])) {
150e32c3607SAndreas Gohr            unset($_SESSION[DOKU_COOKIE]['auth']['time']);
151e32c3607SAndreas Gohr        }
152e32c3607SAndreas Gohr        if(isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) {
153e32c3607SAndreas Gohr            unset($_SESSION[DOKU_COOKIE]['auth']['oauth']);
154e32c3607SAndreas Gohr        }
155e32c3607SAndreas Gohr    }
156e32c3607SAndreas Gohr
157e32c3607SAndreas Gohr    /**
158f866280eSAndreas Gohr     * Find a user by his email address
159f866280eSAndreas Gohr     *
160f866280eSAndreas Gohr     * @param $mail
161f866280eSAndreas Gohr     * @return bool|string
162f866280eSAndreas Gohr     */
16338378fbbSAndreas Gohr    protected function getUserByEmail($mail) {
164f866280eSAndreas Gohr        if($this->users === null) $this->_loadUserData();
16538378fbbSAndreas Gohr        $mail = strtolower($mail);
166f866280eSAndreas Gohr
167f866280eSAndreas Gohr        foreach($this->users as $user => $uinfo) {
168f866280eSAndreas Gohr            if(strtolower($uinfo['mail']) == $mail) return $user;
16938378fbbSAndreas Gohr        }
17038378fbbSAndreas Gohr
171f866280eSAndreas Gohr        return false;
172f866280eSAndreas Gohr    }
17338378fbbSAndreas Gohr
174f866280eSAndreas Gohr    /**
175f866280eSAndreas Gohr     * Enhance function to check aainst duplicate emails
176f866280eSAndreas Gohr     *
177f866280eSAndreas Gohr     * @param string $user
178f866280eSAndreas Gohr     * @param string $pwd
179f866280eSAndreas Gohr     * @param string $name
180f866280eSAndreas Gohr     * @param string $mail
181f866280eSAndreas Gohr     * @param null   $grps
182f866280eSAndreas Gohr     * @return bool|null|string
183f866280eSAndreas Gohr     */
184f866280eSAndreas Gohr    public function createUser($user, $pwd, $name, $mail, $grps = null) {
185f866280eSAndreas Gohr        if($this->getUserByEmail($mail)) {
186f866280eSAndreas Gohr            msg($this->getLang('emailduplicate'), -1);
187f866280eSAndreas Gohr            return false;
188f866280eSAndreas Gohr        }
189f866280eSAndreas Gohr
19038378fbbSAndreas Gohr        return parent::createUser($user, $pwd, $name, $mail, $grps);
19138378fbbSAndreas Gohr    }
19238378fbbSAndreas Gohr
193f866280eSAndreas Gohr    /**
194f866280eSAndreas Gohr     * Enhance function to check aainst duplicate emails
195f866280eSAndreas Gohr     *
196f866280eSAndreas Gohr     * @param string $user
197f866280eSAndreas Gohr     * @param array  $changes
198f866280eSAndreas Gohr     * @return bool
199f866280eSAndreas Gohr     */
20038378fbbSAndreas Gohr    public function modifyUser($user, $changes) {
201f866280eSAndreas Gohr        if(isset($changes['mail']) && $this->getUserByEmail($changes['mail'])) {
202f866280eSAndreas Gohr            msg($this->getLang('emailduplicate'), -1);
203f866280eSAndreas Gohr            return false;
204f866280eSAndreas Gohr        }
20538378fbbSAndreas Gohr
20638378fbbSAndreas Gohr        return parent::modifyUser($user, $changes);
20738378fbbSAndreas Gohr    }
20838378fbbSAndreas Gohr
20980852c15SAndreas Gohr}
21080852c15SAndreas Gohr
21180852c15SAndreas Gohr// vim:ts=4:sw=4:et: