/** * Requests or refreshes an Access Token * $type defaults to 'authorization_code' * * @param string $code * @param null|string $type * * @return User|void */ static function getToken(string $code, string $type = null) { global $Database, $http_response_header; if (empty($type) || !in_array($type, array('authorization_code', 'refresh_token'))) { $type = 'authorization_code'; } $URL_Start = 'https://www.deviantart.com/oauth2/token?client_id=' . DA_CLIENT . '&client_secret=' . DA_SECRET . "&grant_type={$type}"; switch ($type) { case "authorization_code": $json = DeviantArt::request("{$URL_Start}&code={$code}" . OAUTH_REDIRECT_URI, false); break; case "refresh_token": $json = DeviantArt::request("{$URL_Start}&refresh_token={$code}", false); break; } if (empty($json)) { if (Cookie::exists('access')) { $Database->where('access', Cookie::get('access'))->delete('sessions'); Cookie::delete('access', Cookie::HTTPONLY); } HTTP::redirect("/da-auth?error=server_error&error_description={$http_response_header[0]}"); } if (empty($json['status'])) { HTTP::redirect("/da-auth?error={$json['error']}&error_description={$json['error_description']}"); } $userdata = DeviantArt::request('user/whoami', $json['access_token']); /** @var $User Models\User */ $User = $Database->where('id', $userdata['userid'])->getOne('users'); if (isset($User->role) && $User->role === 'ban') { $_GET['error'] = 'user_banned'; $BanReason = $Database->where('target', $User->id)->orderBy('entryid', 'ASC')->getOne('log__banish'); if (!empty($BanReason)) { $_GET['error_description'] = $BanReason['reason']; } return; } $UserID = strtolower($userdata['userid']); $UserData = array('name' => $userdata['username'], 'avatar_url' => URL::makeHttps($userdata['usericon'])); $AuthData = array('access' => $json['access_token'], 'refresh' => $json['refresh_token'], 'expires' => date('c', time() + intval($json['expires_in'])), 'scope' => $json['scope']); $cookie = bin2hex(random_bytes(64)); $AuthData['token'] = sha1($cookie); $browser = CoreUtils::detectBrowser(); foreach ($browser as $k => $v) { if (!empty($v)) { $AuthData[$k] = $v; } } if (empty($User)) { $MoreInfo = array('id' => $UserID, 'role' => 'user'); $makeDev = !$Database->has('users'); if ($makeDev) { $MoreInfo['id'] = strtoupper($MoreInfo['id']); } $Insert = array_merge($UserData, $MoreInfo); $Database->insert('users', $Insert); $User = new User($Insert); if ($makeDev) { $User->updateRole('developer'); } } else { $Database->where('id', $UserID)->update('users', $UserData); } if (empty($makeDev) && !empty($User) && Permission::insufficient('member', $User->role) && $User->isClubMember()) { $User->updateRole('member'); } if ($type === 'refresh_token') { $Database->where('refresh', $code)->update('sessions', $AuthData); } else { $Database->where('user', $User->id)->where('scope', $AuthData['scope'], '!=')->delete('sessions'); $Database->insert('sessions', array_merge($AuthData, array('user' => $UserID))); } $Database->rawQuery("DELETE FROM sessions WHERE \"user\" = ? && lastvisit <= NOW() - INTERVAL '1 MONTH'", array($UserID)); Cookie::set('access', $cookie, time() + Time::$IN_SECONDS['year'], Cookie::HTTPONLY); return $User ?? null; }
/** * Check authentication cookie and set global */ static function authenticate() { global $Database, $signedIn, $currentUser, $Color, $color; CSRFProtection::detect(); if (!POST_REQUEST && isset($_GET['CSRF_TOKEN'])) { HTTP::redirect(CSRFProtection::removeParamFromURL($_SERVER['REQUEST_URI'])); } if (!Cookie::exists('access')) { return; } $authKey = Cookie::get('access'); if (!empty($authKey)) { if (!preg_match(new RegExp('^[a-f\\d]+$', 'iu'), $authKey)) { $oldAuthKey = $authKey; $authKey = bin2hex($authKey); $Database->where('token', sha1($oldAuthKey))->update('sessions', array('token' => sha1($authKey))); Cookie::set('access', $authKey, time() + Time::$IN_SECONDS['year'], Cookie::HTTPONLY); } $currentUser = Users::get(sha1($authKey), 'token'); } if (!empty($currentUser)) { if ($currentUser->role === 'ban') { $Database->where('id', $currentUser->id)->delete('sessions'); } else { if (strtotime($currentUser->Session['expires']) < time()) { $tokenvalid = false; try { DeviantArt::getToken($currentUser->Session['refresh'], 'refresh_token'); $tokenvalid = true; } catch (CURLRequestException $e) { $Database->where('id', $currentUser->Session['id'])->delete('sessions'); trigger_error("Session refresh failed for {$currentUser->name} ({$currentUser->id}) | {$e->getMessage()} (HTTP {$e->getCode()})", E_USER_WARNING); } } else { $tokenvalid = true; } if ($tokenvalid) { $signedIn = true; if (time() - strtotime($currentUser->Session['lastvisit']) > Time::$IN_SECONDS['minute']) { $lastVisitTS = date('c'); if ($Database->where('id', $currentUser->Session['id'])->update('sessions', array('lastvisit' => $lastVisitTS))) { $currentUser->Session['lastvisit'] = $lastVisitTS; } } $_PrefersColour = array('Pirill-Poveniy' => true, 'itv-canterlot' => true); if (isset($_PrefersColour[$currentUser->name])) { $Color = 'Colour'; $color = 'colour'; } } } } else { Cookie::delete('access', Cookie::HTTPONLY); } }