1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-30 01:10:58 +01:00

Consolidate use of magical cookie name strings

Summary: Ref T4339. We have more magical cookie names than we should, move them all to a central location.

Test Plan: Registered, logged in, linked account, logged out. See inlines.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4339

Differential Revision: https://secure.phabricator.com/D8041
This commit is contained in:
epriestley 2014-01-23 14:01:35 -08:00
parent 02aa193cb0
commit 0727418023
15 changed files with 116 additions and 46 deletions

View file

@ -1319,6 +1319,7 @@ phutil_register_library_map(array(
'PhabricatorContentSource' => 'applications/metamta/contentsource/PhabricatorContentSource.php',
'PhabricatorContentSourceView' => 'applications/metamta/contentsource/PhabricatorContentSourceView.php',
'PhabricatorController' => 'applications/base/controller/PhabricatorController.php',
'PhabricatorCookies' => 'applications/auth/constants/PhabricatorCookies.php',
'PhabricatorCoreConfigOptions' => 'applications/config/option/PhabricatorCoreConfigOptions.php',
'PhabricatorCountdown' => 'applications/countdown/storage/PhabricatorCountdown.php',
'PhabricatorCountdownCapabilityDefaultView' => 'applications/countdown/capability/PhabricatorCountdownCapabilityDefaultView.php',
@ -3934,6 +3935,7 @@ phutil_register_library_map(array(
'PhabricatorConpherencePHIDTypeThread' => 'PhabricatorPHIDType',
'PhabricatorContentSourceView' => 'AphrontView',
'PhabricatorController' => 'AphrontController',
'PhabricatorCookies' => 'Phobject',
'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorCountdown' =>
array(

View file

@ -58,12 +58,17 @@ final class DarkConsoleDataController extends PhabricatorController {
$panel = $obj->renderPanel();
if (!empty($_COOKIE['phsid'])) {
$panel = PhutilSafeHTML::applyFunction(
'str_replace',
$_COOKIE['phsid'],
'(session-key)',
$panel);
// Because cookie names can now be prefixed, wipe out any cookie value
// with the session cookie name anywhere in its name.
$pattern = '('.preg_quote(PhabricatorCookies::COOKIE_SESSION).')';
foreach ($_COOKIE as $cookie_name => $cookie_value) {
if (preg_match($pattern, $cookie_name)) {
$panel = PhutilSafeHTML::applyFunction(
'str_replace',
$cookie_value,
'(session-key)',
$panel);
}
}
$output['panel'][$class] = $panel;

View file

@ -0,0 +1,48 @@
<?php
/**
* Consolidates Phabricator application cookies, including registration
* and session management.
*/
final class PhabricatorCookies extends Phobject {
/**
* Stores the login username for password authentication. This is just a
* display value for convenience, used to prefill the login form. It is not
* authoritative.
*/
const COOKIE_USERNAME = 'phusr';
/**
* Stores the user's current session ID. This is authoritative and establishes
* the user's identity.
*/
const COOKIE_SESSION = 'phsid';
/**
* Stores a secret used during new account registration to prevent an attacker
* from tricking a victim into registering an account which is linked to
* credentials the attacker controls.
*/
const COOKIE_REGISTRATION = 'phreg';
/**
* Stores a secret used during OAuth2 handshakes to prevent various attacks
* where an attacker hands a victim a URI corresponding to the middle of an
* OAuth2 workflow and we might otherwise do something sketchy. Particularly,
* this corresponds to the OAuth2 "code".
*/
const COOKIE_CLIENTID = 'phcid';
/**
* Stores the URI to redirect the user to after login. This allows users to
* visit a path like `/feed/`, be prompted to login, and then be redirected
* back to `/feed/` after the workflow completes.
*/
const COOKIE_NEXTURI = 'next_uri';
}

View file

@ -88,8 +88,12 @@ abstract class PhabricatorAuthController extends PhabricatorController {
// there's no check for users being disabled here.
$request = $this->getRequest();
$request->setCookie('phusr', $user->getUsername());
$request->setCookie('phsid', $session_key);
$request->setCookie(
PhabricatorCookies::COOKIE_USERNAME,
$user->getUsername());
$request->setCookie(
PhabricatorCookies::COOKIE_SESSION,
$session_key);
$this->clearRegistrationCookies();
}
@ -101,15 +105,15 @@ abstract class PhabricatorAuthController extends PhabricatorController {
$request = $this->getRequest();
// Clear the registration key.
$request->clearCookie('phreg');
$request->clearCookie(PhabricatorCookies::COOKIE_REGISTRATION);
// Clear the client ID / OAuth state key.
$request->clearCookie('phcid');
$request->clearCookie(PhabricatorCookies::COOKIE_CLIENTID);
}
private function buildLoginValidateResponse(PhabricatorUser $user) {
$validate_uri = new PhutilURI($this->getApplicationURI('validate/'));
$validate_uri->setQueryParam('phusr', $user->getUsername());
$validate_uri->setQueryParam('expect', $user->getUsername());
return id(new AphrontRedirectResponse())->setURI((string)$validate_uri);
}
@ -168,7 +172,8 @@ abstract class PhabricatorAuthController extends PhabricatorController {
return array($account, $provider, $response);
}
$registration_key = $request->getCookie('phreg');
$registration_key = $request->getCookie(
PhabricatorCookies::COOKIE_REGISTRATION);
// NOTE: This registration key check is not strictly necessary, because
// we're only creating new accounts, not linking existing accounts. It
@ -181,7 +186,7 @@ abstract class PhabricatorAuthController extends PhabricatorController {
// since you could have simply completed the process yourself.
if (!$registration_key) {
$response = $this->renderError(
$response = $this->renderError(
pht(
'Your browser did not submit a registration key with the request. '.
'You must use the same browser to begin and complete registration. '.

View file

@ -79,7 +79,10 @@ final class PhabricatorAuthLinkController
$panel_uri = '/settings/panel/external/';
$request->setCookie('phcid', Filesystem::readRandomCharacters(16));
$request->setCookie(
PhabricatorCookies::COOKIE_CLIENTID,
Filesystem::readRandomCharacters(16));
switch ($this->action) {
case 'link':
$form = $provider->buildLinkForm($this);

View file

@ -166,7 +166,9 @@ final class PhabricatorAuthLoginController
$account->save();
unset($unguarded);
$this->getRequest()->setCookie('phreg', $registration_key);
$this->getRequest()->setCookie(
PhabricatorCookies::COOKIE_REGISTRATION,
$registration_key);
return id(new AphrontRedirectResponse())->setURI($next_uri);
}

View file

@ -24,10 +24,10 @@ final class PhabricatorAuthStartController
return $this->processConduitRequest();
}
if ($request->getCookie('phusr') && $request->getCookie('phsid')) {
if (strlen($request->getCookie(PhabricatorCookies::COOKIE_SESSION))) {
// The session cookie is invalid, so clear it.
$request->clearCookie('phusr');
$request->clearCookie('phsid');
$request->clearCookie(PhabricatorCookies::COOKIE_USERNAME);
$request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
return $this->renderError(
pht(
@ -71,8 +71,12 @@ final class PhabricatorAuthStartController
}
if (!$request->isFormPost()) {
$request->setCookie('next_uri', $next_uri);
$request->setCookie('phcid', Filesystem::readRandomCharacters(16));
$request->setCookie(
PhabricatorCookies::COOKIE_NEXTURI,
$next_uri);
$request->setCookie(
PhabricatorCookies::COOKIE_CLIENTID,
Filesystem::readRandomCharacters(16));
}
$not_buttons = array();

View file

@ -13,7 +13,7 @@ final class PhabricatorAuthValidateController
$failures = array();
if (!strlen($request->getStr('phusr'))) {
if (!strlen($request->getStr('expect'))) {
return $this->renderErrors(
array(
pht(
@ -21,8 +21,8 @@ final class PhabricatorAuthValidateController
'phusr')));
}
$expect_phusr = $request->getStr('phusr');
$actual_phusr = $request->getCookie('phusr');
$expect_phusr = $request->getStr('expect');
$actual_phusr = $request->getCookie(PhabricatorCookies::COOKIE_USERNAME);
if ($actual_phusr != $expect_phusr) {
if ($actual_phusr) {
$failures[] = pht(
@ -54,8 +54,8 @@ final class PhabricatorAuthValidateController
return $this->renderErrors($failures);
}
$next = $request->getCookie('next_uri');
$request->clearCookie('next_uri');
$next = $request->getCookie(PhabricatorCookies::COOKIE_NEXTURI);
$request->clearCookie(PhabricatorCookies::COOKIE_NEXTURI);
if (!PhabricatorEnv::isValidLocalWebResource($next)) {
$next = '/';

View file

@ -86,7 +86,7 @@ final class PhabricatorEmailTokenController
));
}
$request->setCookie('next_uri', $next);
$request->setCookie(PhabricatorCookies::COOKIE_NEXTURI, $next);
return $this->loginUser($target_user);
}

View file

@ -32,8 +32,8 @@ final class PhabricatorLogoutController
// Destroy the user's session in the database so logout works even if
// their cookies have some issues. We'll detect cookie issues when they
// try to login again and tell them to clear any junk.
$phsid = $request->getCookie('phsid');
if ($phsid) {
$phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
if (strlen($phsid)) {
$session = id(new PhabricatorAuthSessionQuery())
->setViewer($user)
->withSessionKeys(array($phsid))
@ -42,7 +42,7 @@ final class PhabricatorLogoutController
$session->delete();
}
}
$request->clearCookie('phsid');
$request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
return id(new AphrontRedirectResponse())
->setURI('/login/');
@ -52,8 +52,7 @@ final class PhabricatorLogoutController
$dialog = id(new AphrontDialogView())
->setUser($user)
->setTitle(pht('Log out of Phabricator?'))
->appendChild(phutil_tag('p', array(), pht(
'Are you sure you want to log out?')))
->appendChild(pht('Are you sure you want to log out?'))
->addSubmitButton(pht('Logout'))
->addCancelButton('/');

View file

@ -35,9 +35,11 @@ abstract class PhabricatorAuthProviderOAuth extends PhabricatorAuthProvider {
protected function renderLoginForm(AphrontRequest $request, $mode) {
$adapter = $this->getAdapter();
$adapter->setState(PhabricatorHash::digest($request->getCookie('phcid')));
$adapter->setState(
PhabricatorHash::digest(
$request->getCookie(PhabricatorCookies::COOKIE_CLIENTID)));
$scope = $request->getStr("scope");
$scope = $request->getStr('scope');
if ($scope) {
$adapter->setScope($scope);
}
@ -81,14 +83,15 @@ abstract class PhabricatorAuthProviderOAuth extends PhabricatorAuthProvider {
}
if ($adapter->supportsStateParameter()) {
$phcid = $request->getCookie('phcid');
$phcid = $request->getCookie(PhabricatorCookies::COOKIE_CLIENTID);
if (!strlen($phcid)) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'Your browser did not submit a "phcid" cookie with OAuth state '.
'Your browser did not submit a "%s" cookie with OAuth state '.
'information in the request. Check that cookies are enabled. '.
'If this problem persists, you may need to clear your cookies.'));
'If this problem persists, you may need to clear your cookies.',
PhabricatorCookies::COOKIE_CLIENTID));
}
$state = $request->getStr('state');

View file

@ -87,7 +87,7 @@ final class PhabricatorAuthProviderPassword
$v_user = nonempty(
$request->getStr('username'),
$request->getCookie('phusr'));
$request->getCookie(PhabricatorCookies::COOKIE_USERNAME));
$e_user = null;
$e_pass = null;
@ -191,8 +191,8 @@ final class PhabricatorAuthProviderPassword
PhabricatorUserLog::ACTION_LOGIN_FAILURE);
$log->save();
$request->clearCookie('phusr');
$request->clearCookie('phsid');
$request->clearCookie(PhabricatorCookies::COOKIE_USERNAME);
$request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
$response = $controller->buildProviderPageResponse(
$this,

View file

@ -35,7 +35,7 @@ abstract class PhabricatorController extends AphrontController {
} else {
$user = new PhabricatorUser();
$phsid = $request->getCookie('phsid');
$phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
if ($phsid) {
$session_user = id(new PhabricatorAuthSessionEngine())
->loadUserForSession(PhabricatorAuthSession::TYPE_WEB, $phsid);

View file

@ -66,7 +66,9 @@ final class PhabricatorUserLog extends PhabricatorUserDAO {
$this->remoteAddr = idx($_SERVER, 'REMOTE_ADDR', '');
}
if (!$this->session) {
$this->setSession(idx($_COOKIE, 'phsid'));
// TODO: This is not correct if there's a cookie prefix. This object
// should take an AphrontRequest.
$this->setSession(idx($_COOKIE, PhabricatorCookies::COOKIE_SESSION));
}
$this->details['host'] = php_uname('n');
$this->details['user_agent'] = AphrontRequest::getHTTPHeader('User-Agent');

View file

@ -40,11 +40,8 @@ final class PhabricatorSettingsPanelSessions
->withPHIDs($identity_phids)
->execute();
// TODO: Once this has a real ID column, use that instead.
$sessions = msort($sessions, 'getSessionStart');
$sessions = array_reverse($sessions);
$current_key = PhabricatorHash::digest($request->getCookie('phsid'));
$current_key = PhabricatorHash::digest(
$request->getCookie(PhabricatorCookies::COOKIE_SESSION));
$rows = array();
$rowc = array();