Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/engine/PhabricatorAuthSessionEngine.php
Show First 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | switch ($session_type) { | ||||
if (!$user->canEstablishWebSessions()) { | if (!$user->canEstablishWebSessions()) { | ||||
return null; | return null; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
$session = id(new PhabricatorAuthSession())->loadFromArray($session_dict); | $session = id(new PhabricatorAuthSession())->loadFromArray($session_dict); | ||||
$ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type); | $this->extendSession($session); | ||||
// If more than 20% of the time on this session has been used, refresh the | |||||
// TTL back up to the full duration. The idea here is that sessions are | |||||
// good forever if used regularly, but get GC'd when they fall out of use. | |||||
// NOTE: If we begin rotating session keys when extending sessions, the | |||||
// CSRF code needs to be updated so CSRF tokens survive session rotation. | |||||
if (time() + (0.80 * $ttl) > $session->getSessionExpires()) { | |||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||||
$conn_w = $session_table->establishConnection('w'); | |||||
queryfx( | |||||
$conn_w, | |||||
'UPDATE %T SET sessionExpires = UNIX_TIMESTAMP() + %d WHERE id = %d', | |||||
$session->getTableName(), | |||||
$ttl, | |||||
$session->getID()); | |||||
unset($unguarded); | |||||
} | |||||
// TODO: Remove this, see T13225. | // TODO: Remove this, see T13225. | ||||
if ($is_weak) { | if ($is_weak) { | ||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | ||||
$conn_w = $session_table->establishConnection('w'); | $conn_w = $session_table->establishConnection('w'); | ||||
queryfx( | queryfx( | ||||
$conn_w, | $conn_w, | ||||
'UPDATE %T SET sessionKey = %P WHERE id = %d', | 'UPDATE %T SET sessionKey = %P WHERE id = %d', | ||||
Show All 35 Lines | public function establishSession($session_type, $identity_phid, $partial) { | ||||
if ($identity_phid === null) { | if ($identity_phid === null) { | ||||
return self::KIND_ANONYMOUS.'/'.$session_key; | return self::KIND_ANONYMOUS.'/'.$session_key; | ||||
} | } | ||||
$session_table = new PhabricatorAuthSession(); | $session_table = new PhabricatorAuthSession(); | ||||
$conn_w = $session_table->establishConnection('w'); | $conn_w = $session_table->establishConnection('w'); | ||||
// This has a side effect of validating the session type. | // This has a side effect of validating the session type. | ||||
$session_ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type); | $session_ttl = PhabricatorAuthSession::getSessionTypeTTL( | ||||
$session_type, | |||||
$partial); | |||||
$digest_key = PhabricatorAuthSession::newSessionDigest( | $digest_key = PhabricatorAuthSession::newSessionDigest( | ||||
new PhutilOpaqueEnvelope($session_key)); | new PhutilOpaqueEnvelope($session_key)); | ||||
// Logging-in users don't have CSRF stuff yet, so we have to unguard this | // Logging-in users don't have CSRF stuff yet, so we have to unguard this | ||||
// write. | // write. | ||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | ||||
id(new PhabricatorAuthSession()) | id(new PhabricatorAuthSession()) | ||||
▲ Show 20 Lines • Show All 785 Lines • ▼ Show 20 Lines | public function willServeRequestForUser(PhabricatorUser $user) { | ||||
PhabricatorEnv::setLocaleCode($user->getTranslation()); | PhabricatorEnv::setLocaleCode($user->getTranslation()); | ||||
$extensions = PhabricatorAuthSessionEngineExtension::getAllExtensions(); | $extensions = PhabricatorAuthSessionEngineExtension::getAllExtensions(); | ||||
foreach ($extensions as $extension) { | foreach ($extensions as $extension) { | ||||
$extension->willServeRequestForUser($user); | $extension->willServeRequestForUser($user); | ||||
} | } | ||||
} | } | ||||
private function extendSession(PhabricatorAuthSession $session) { | |||||
$is_partial = $session->getIsPartial(); | |||||
// Don't extend partial sessions. You have a relatively short window to | |||||
// upgrade into a full session, and your session expires otherwise. | |||||
if ($is_partial) { | |||||
return; | |||||
} | |||||
$session_type = $session->getType(); | |||||
$ttl = PhabricatorAuthSession::getSessionTypeTTL( | |||||
$session_type, | |||||
$session->getIsPartial()); | |||||
// If more than 20% of the time on this session has been used, refresh the | |||||
// TTL back up to the full duration. The idea here is that sessions are | |||||
// good forever if used regularly, but get GC'd when they fall out of use. | |||||
$now = PhabricatorTime::getNow(); | |||||
if ($now + (0.80 * $ttl) <= $session->getSessionExpires()) { | |||||
return; | |||||
} | |||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||||
queryfx( | |||||
$session->establishConnection('w'), | |||||
'UPDATE %R SET sessionExpires = UNIX_TIMESTAMP() + %d | |||||
WHERE id = %d', | |||||
$session, | |||||
$ttl, | |||||
$session->getID()); | |||||
unset($unguarded); | |||||
} | |||||
} | } |