Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/auth/constants/PhabricatorCookies.php
12256 views
1
<?php
2
3
/**
4
* Consolidates Phabricator application cookies, including registration
5
* and session management.
6
*
7
* @task clientid Client ID Cookie
8
* @task next Next URI Cookie
9
*/
10
final class PhabricatorCookies extends Phobject {
11
12
/**
13
* Stores the login username for password authentication. This is just a
14
* display value for convenience, used to prefill the login form. It is not
15
* authoritative.
16
*/
17
const COOKIE_USERNAME = 'phusr';
18
19
20
/**
21
* Stores the user's current session ID. This is authoritative and establishes
22
* the user's identity.
23
*/
24
const COOKIE_SESSION = 'phsid';
25
26
27
/**
28
* Stores a secret used during new account registration to prevent an attacker
29
* from tricking a victim into registering an account which is linked to
30
* credentials the attacker controls.
31
*/
32
const COOKIE_REGISTRATION = 'phreg';
33
34
35
/**
36
* Stores a secret used during OAuth2 handshakes to prevent various attacks
37
* where an attacker hands a victim a URI corresponding to the middle of an
38
* OAuth2 workflow and we might otherwise do something sketchy. Particularly,
39
* this corresponds to the OAuth2 "code".
40
*/
41
const COOKIE_CLIENTID = 'phcid';
42
43
44
/**
45
* Stores the URI to redirect the user to after login. This allows users to
46
* visit a path like `/feed/`, be prompted to login, and then be redirected
47
* back to `/feed/` after the workflow completes.
48
*/
49
const COOKIE_NEXTURI = 'next_uri';
50
51
52
/**
53
* Stores a hint that the user should be moved directly into high security
54
* after upgrading a partial login session. This is used during password
55
* recovery to avoid a double-prompt.
56
*/
57
const COOKIE_HISEC = 'jump_to_hisec';
58
59
60
/**
61
* Stores an invite code.
62
*/
63
const COOKIE_INVITE = 'invite';
64
65
66
/**
67
* Stores a workflow completion across a redirect-after-POST following a
68
* form submission. This can be used to show "Changes Saved" messages.
69
*/
70
const COOKIE_SUBMIT = 'phfrm';
71
72
73
/* -( Client ID Cookie )--------------------------------------------------- */
74
75
76
/**
77
* Set the client ID cookie. This is a random cookie used like a CSRF value
78
* during authentication workflows.
79
*
80
* @param AphrontRequest Request to modify.
81
* @return void
82
* @task clientid
83
*/
84
public static function setClientIDCookie(AphrontRequest $request) {
85
86
// NOTE: See T3471 for some discussion. Some browsers and browser extensions
87
// can make duplicate requests, so we overwrite this cookie only if it is
88
// not present in the request. The cookie lifetime is limited by making it
89
// temporary and clearing it when users log out.
90
91
$value = $request->getCookie(self::COOKIE_CLIENTID);
92
if ($value === null || !strlen($value)) {
93
$request->setTemporaryCookie(
94
self::COOKIE_CLIENTID,
95
Filesystem::readRandomCharacters(16));
96
}
97
}
98
99
100
/* -( Next URI Cookie )---------------------------------------------------- */
101
102
103
/**
104
* Set the Next URI cookie. We only write the cookie if it wasn't recently
105
* written, to avoid writing over a real URI with a bunch of "humans.txt"
106
* stuff. See T3793 for discussion.
107
*
108
* @param AphrontRequest Request to write to.
109
* @param string URI to write.
110
* @param bool Write this cookie even if we have a fresh
111
* cookie already.
112
* @return void
113
*
114
* @task next
115
*/
116
public static function setNextURICookie(
117
AphrontRequest $request,
118
$next_uri,
119
$force = false) {
120
121
if (!$force) {
122
$cookie_value = $request->getCookie(self::COOKIE_NEXTURI);
123
list($set_at, $current_uri) = self::parseNextURICookie($cookie_value);
124
125
// If the cookie was set within the last 2 minutes, don't overwrite it.
126
// Primarily, this prevents browser requests for resources which do not
127
// exist (like "humans.txt" and various icons) from overwriting a normal
128
// URI like "/feed/".
129
if ($set_at > (time() - 120)) {
130
return;
131
}
132
}
133
134
$new_value = time().','.$next_uri;
135
$request->setTemporaryCookie(self::COOKIE_NEXTURI, $new_value);
136
}
137
138
139
/**
140
* Read the URI out of the Next URI cookie.
141
*
142
* @param AphrontRequest Request to examine.
143
* @return string|null Next URI cookie's URI value.
144
*
145
* @task next
146
*/
147
public static function getNextURICookie(AphrontRequest $request) {
148
$cookie_value = $request->getCookie(self::COOKIE_NEXTURI);
149
list($set_at, $next_uri) = self::parseNextURICookie($cookie_value);
150
151
return $next_uri;
152
}
153
154
155
/**
156
* Parse a Next URI cookie into its components.
157
*
158
* @param string Raw cookie value.
159
* @return list<string> List of timestamp and URI.
160
*
161
* @task next
162
*/
163
private static function parseNextURICookie($cookie) {
164
// Old cookies look like: /uri
165
// New cookies look like: timestamp,/uri
166
167
if (!phutil_nonempty_string($cookie)) {
168
return null;
169
}
170
171
if (strpos($cookie, ',') !== false) {
172
list($timestamp, $uri) = explode(',', $cookie, 2);
173
return array((int)$timestamp, $uri);
174
}
175
176
return array(0, $cookie);
177
}
178
179
}
180
181