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; 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 return $_SESSION[DOKU_COOKIE]['auth']['oauth'] ?? false; 56 } 57 58 /** 59 * Clear login environment after login 60 * 61 * @return void 62 */ 63 public function clearLoginData() 64 { 65 if (isset($_SESSION[DOKU_COOKIE]['auth']['oauth'])) { 66 unset($_SESSION[DOKU_COOKIE]['auth']['oauth']); 67 } 68 } 69 70 /** 71 * This basically duplicates what DokuWiki does when a user is logged in 72 * 73 * @param array $userdata 74 * @param bool $resettime Set a new session time? False only when restoring from session 75 * @return void 76 * @throws Exception 77 */ 78 public function setUser($userdata, $resettime = true) 79 { 80 global $USERINFO; 81 82 if ( 83 !isset($userdata['user']) || 84 !isset($userdata['name']) || 85 !isset($userdata['mail']) || 86 !isset($userdata['grps']) || 87 !is_array($userdata['grps']) 88 ) { 89 throw new Exception('Missing user data, cannot save to session'); 90 } 91 92 $USERINFO = $userdata; 93 $_SERVER['REMOTE_USER'] = $userdata['user']; 94 95 $_SESSION[DOKU_COOKIE]['auth']['user'] = $userdata['user']; 96 $_SESSION[DOKU_COOKIE]['auth']['pass'] = 'not-set'; // pass is neither needed nor wanted 97 $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 98 $_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid(); 99 if ($resettime) { 100 $_SESSION[DOKU_COOKIE]['auth']['time'] = time(); 101 } 102 } 103 104 /** 105 * The user data currently saved in the session if any 106 * 107 * @return false|array 108 */ 109 public function getUser() 110 { 111 return $_SESSION[DOKU_COOKIE]['auth']['info'] ?? false; 112 } 113 114 /** 115 * Set oAuth info to cookie 116 * 117 * We use the same cookie as standard DokuWiki, but write different info. 118 * 119 * @param string $servicename 120 * @param string $storageId 121 * @return void 122 */ 123 public function setCookie($servicename, $storageId) 124 { 125 global $conf; 126 $validityPeriodInSeconds = 60 * 60 * 24 * 365; 127 $cookie = "$servicename|oauth|$storageId"; 128 $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir']; 129 $time = time() + $validityPeriodInSeconds; 130 setcookie( 131 DOKU_COOKIE, 132 $cookie, 133 [ 134 'expires' => $time, 135 'path' => $cookieDir, 136 'domain' => '', 137 'secure' => $conf['securecookie'] && is_ssl(), 138 'httponly' => true 139 ] 140 ); 141 } 142 143 /** 144 * Get oAuth info from cookie 145 * 146 * @return array|false Either [servicename=>?, storageID=>?] or false if no oauth data in cookie 147 */ 148 public function getCookie() 149 { 150 if (!isset($_COOKIE[DOKU_COOKIE])) return false; 151 [$servicename, $oauth, $storageId] = explode('|', $_COOKIE[DOKU_COOKIE]); 152 if ($oauth !== 'oauth') return false; 153 return ['servicename' => $servicename, 'storageId' => $storageId]; 154 } 155 156 /** 157 * Is any auth data in the session currently trustworthy? 158 * @return bool 159 */ 160 public function isValid() 161 { 162 global $conf; 163 164 if (!isset($_SESSION[DOKU_COOKIE]['auth']['buid'])) return false; 165 if (!isset($_SESSION[DOKU_COOKIE]['auth']['time'])) return false; 166 if ($_SESSION[DOKU_COOKIE]['auth']['buid'] != auth_browseruid()) return false; 167 if ($_SESSION[DOKU_COOKIE]['auth']['time'] < time() - $conf['auth_security_timeout']) return false; 168 169 return true; 170 } 171 172 /** 173 * Clear the session from auth related data 174 * @return void 175 */ 176 public function clear() 177 { 178 //FIXME clear cookie? 179 $this->clearLoginData(); 180 } 181} 182