Path: blob/master/src/applications/auth/constants/PhabricatorCookies.php
12256 views
<?php12/**3* Consolidates Phabricator application cookies, including registration4* and session management.5*6* @task clientid Client ID Cookie7* @task next Next URI Cookie8*/9final class PhabricatorCookies extends Phobject {1011/**12* Stores the login username for password authentication. This is just a13* display value for convenience, used to prefill the login form. It is not14* authoritative.15*/16const COOKIE_USERNAME = 'phusr';171819/**20* Stores the user's current session ID. This is authoritative and establishes21* the user's identity.22*/23const COOKIE_SESSION = 'phsid';242526/**27* Stores a secret used during new account registration to prevent an attacker28* from tricking a victim into registering an account which is linked to29* credentials the attacker controls.30*/31const COOKIE_REGISTRATION = 'phreg';323334/**35* Stores a secret used during OAuth2 handshakes to prevent various attacks36* where an attacker hands a victim a URI corresponding to the middle of an37* OAuth2 workflow and we might otherwise do something sketchy. Particularly,38* this corresponds to the OAuth2 "code".39*/40const COOKIE_CLIENTID = 'phcid';414243/**44* Stores the URI to redirect the user to after login. This allows users to45* visit a path like `/feed/`, be prompted to login, and then be redirected46* back to `/feed/` after the workflow completes.47*/48const COOKIE_NEXTURI = 'next_uri';495051/**52* Stores a hint that the user should be moved directly into high security53* after upgrading a partial login session. This is used during password54* recovery to avoid a double-prompt.55*/56const COOKIE_HISEC = 'jump_to_hisec';575859/**60* Stores an invite code.61*/62const COOKIE_INVITE = 'invite';636465/**66* Stores a workflow completion across a redirect-after-POST following a67* form submission. This can be used to show "Changes Saved" messages.68*/69const COOKIE_SUBMIT = 'phfrm';707172/* -( Client ID Cookie )--------------------------------------------------- */737475/**76* Set the client ID cookie. This is a random cookie used like a CSRF value77* during authentication workflows.78*79* @param AphrontRequest Request to modify.80* @return void81* @task clientid82*/83public static function setClientIDCookie(AphrontRequest $request) {8485// NOTE: See T3471 for some discussion. Some browsers and browser extensions86// can make duplicate requests, so we overwrite this cookie only if it is87// not present in the request. The cookie lifetime is limited by making it88// temporary and clearing it when users log out.8990$value = $request->getCookie(self::COOKIE_CLIENTID);91if ($value === null || !strlen($value)) {92$request->setTemporaryCookie(93self::COOKIE_CLIENTID,94Filesystem::readRandomCharacters(16));95}96}979899/* -( Next URI Cookie )---------------------------------------------------- */100101102/**103* Set the Next URI cookie. We only write the cookie if it wasn't recently104* written, to avoid writing over a real URI with a bunch of "humans.txt"105* stuff. See T3793 for discussion.106*107* @param AphrontRequest Request to write to.108* @param string URI to write.109* @param bool Write this cookie even if we have a fresh110* cookie already.111* @return void112*113* @task next114*/115public static function setNextURICookie(116AphrontRequest $request,117$next_uri,118$force = false) {119120if (!$force) {121$cookie_value = $request->getCookie(self::COOKIE_NEXTURI);122list($set_at, $current_uri) = self::parseNextURICookie($cookie_value);123124// If the cookie was set within the last 2 minutes, don't overwrite it.125// Primarily, this prevents browser requests for resources which do not126// exist (like "humans.txt" and various icons) from overwriting a normal127// URI like "/feed/".128if ($set_at > (time() - 120)) {129return;130}131}132133$new_value = time().','.$next_uri;134$request->setTemporaryCookie(self::COOKIE_NEXTURI, $new_value);135}136137138/**139* Read the URI out of the Next URI cookie.140*141* @param AphrontRequest Request to examine.142* @return string|null Next URI cookie's URI value.143*144* @task next145*/146public static function getNextURICookie(AphrontRequest $request) {147$cookie_value = $request->getCookie(self::COOKIE_NEXTURI);148list($set_at, $next_uri) = self::parseNextURICookie($cookie_value);149150return $next_uri;151}152153154/**155* Parse a Next URI cookie into its components.156*157* @param string Raw cookie value.158* @return list<string> List of timestamp and URI.159*160* @task next161*/162private static function parseNextURICookie($cookie) {163// Old cookies look like: /uri164// New cookies look like: timestamp,/uri165166if (!phutil_nonempty_string($cookie)) {167return null;168}169170if (strpos($cookie, ',') !== false) {171list($timestamp, $uri) = explode(',', $cookie, 2);172return array((int)$timestamp, $uri);173}174175return array(0, $cookie);176}177178}179180181