1<?php
2
3namespace dokuwiki\plugin\oauth;
4
5/**
6 * Singleton to manage all oAuth related session and cookie data
7 */
8class Session
9{
10    /** @var Session */
11    protected static $instance = null;
12
13    /**
14     * hidden constructor
15     */
16    protected function __construct()
17    {
18    }
19
20    /**
21     * Get Singleton Instance
22     *
23     * @return Session
24     */
25    public static function getInstance()
26    {
27        if (self::$instance === null) {
28            self::$instance = new Session();
29        }
30        return self::$instance;
31    }
32
33    /**
34     * Set the environment needed to verify a login in progress
35     *
36     * @param string $servicename the name of the service used
37     * @param string $id pageID to return to after login
38     * @return void
39     */
40    public function setLoginData($servicename, $id)
41    {
42        $_SESSION[DOKU_COOKIE]['auth']['oauth'] = [
43            'servicename' => $servicename,
44            'id' => $id,
45        ];
46    }
47
48    /**
49     * Get the current login environment
50     *
51     * @return false|array Either [servicename=>*, id=>*] or false
52     */
53    public function getLoginData()
54    {
55        if (isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) {
56            return $_SESSION[DOKU_COOKIE]['auth']['oauth'];
57        }
58        return false;
59    }
60
61    /**
62     * Clear login environment after login
63     *
64     * @return void
65     */
66    public function clearLoginData()
67    {
68        if (isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) {
69            unset($_SESSION[DOKU_COOKIE]['auth']['oauth']);
70        }
71    }
72
73    /**
74     * This basically duplicates what DokuWiki does when a user is logged in
75     *
76     * @param array $userdata
77     * @param bool $resettime Set a new session time? False only when restoring from session
78     * @return void
79     * @throws Exception
80     */
81    public function setUser($userdata, $resettime = true)
82    {
83        global $USERINFO;
84
85        if (
86            !isset($userdata['user']) or
87            !isset($userdata['name']) or
88            !isset($userdata['mail']) or
89            !isset($userdata['grps']) or
90            !is_array($userdata['grps'])
91        ) {
92            throw new Exception('Missing user data, cannot save to session');
93        }
94
95        $USERINFO = $userdata;
96        $_SERVER['REMOTE_USER'] = $userdata['user'];
97
98        $_SESSION[DOKU_COOKIE]['auth']['user'] = $userdata['user'];
99        $_SESSION[DOKU_COOKIE]['auth']['pass'] = 'not-set'; // pass is neither needed nor wanted
100        $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
101        $_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid();
102        if ($resettime) {
103            $_SESSION[DOKU_COOKIE]['auth']['time'] = time();
104        }
105    }
106
107    /**
108     * The user data currently saved in the session if any
109     *
110     * @return false|array
111     */
112    public function getUser()
113    {
114        if (isset($_SESSION[DOKU_COOKIE]['auth']['info'])) {
115            return $_SESSION[DOKU_COOKIE]['auth']['info'];
116        }
117        return false;
118    }
119
120    /**
121     * Set oAuth info to cookie
122     *
123     * We use the same cookie as standard DokuWiki, but write different info.
124     *
125     * @param string $servicename
126     * @param string $storageId
127     * @return void
128     */
129    public function setCookie($servicename, $storageId)
130    {
131        global $conf;
132        $validityPeriodInSeconds = 60 * 60 * 24 * 365;
133        $cookie = "$servicename|oauth|$storageId";
134        $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
135        $time = time() + $validityPeriodInSeconds;
136        setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true);
137    }
138
139    /**
140     * Get oAuth info from cookie
141     *
142     * @return array|false Either [servicename=>?, storageID=>?] or false if no oauth data in cookie
143     */
144    public function getCookie()
145    {
146        if (!isset($_COOKIE[DOKU_COOKIE])) return false;
147        list($servicename, $oauth, $storageId) = explode('|', $_COOKIE[DOKU_COOKIE]);
148        if ($oauth !== 'oauth') return false;
149        return ['servicename' => $servicename, 'storageId' => $storageId];
150    }
151
152    /**
153     * Is any auth data in the session currently trustworthy?
154     * @return bool
155     */
156    public function isValid()
157    {
158        global $conf;
159
160        if (!isset($_SESSION[DOKU_COOKIE]['auth']['buid'])) return false;
161        if (!isset($_SESSION[DOKU_COOKIE]['auth']['time'])) return false;
162        if ($_SESSION[DOKU_COOKIE]['auth']['buid'] != auth_browseruid()) return false;
163        if ($_SESSION[DOKU_COOKIE]['auth']['time'] < time() - $conf['auth_security_timeout']) return false;
164
165        return true;
166    }
167
168    /**
169     * Clear the session from auth related data
170     * @return void
171     */
172    public function clear()
173    {
174        //FIXME clear cookie?
175        $this->clearLoginData();
176
177    }
178}
179