@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Support "state" parameter in OAuth

Summary:
Ref T1445. Ref T1536. Although we have separate CSRF protection and have never been vulnerable to OAuth hijacking, properly implementing the "state" parameter provides a little more certainty.

Before OAuth, we set a random value on the client, and pass its hash as the "state" parameter. Upon return, validate that (a) the user has a nonempty "phcid" cookie and (b) the OAuth endpoint passed back the correct state (the hash of that cookie).

Test Plan: Logged in with all OAuth providers, which all apparently support `state`.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran, arice

Maniphest Tasks: T1445, T1536

Differential Revision: https://secure.phabricator.com/D6179

+33 -1
+3
src/aphront/AphrontRequest.php
··· 275 275 276 276 final public function clearCookie($name) { 277 277 $this->setCookie($name, '', time() - (60 * 60 * 24 * 30)); 278 + unset($_COOKIE[$name]); 278 279 } 279 280 280 281 final public function setCookie($name, $value, $expire = null) { ··· 317 318 $base_domain, 318 319 $is_secure, 319 320 $http_only = true); 321 + 322 + $_COOKIE[$name] = $value; 320 323 321 324 return $this; 322 325 }
+5
src/applications/auth/controller/PhabricatorAuthController.php
··· 39 39 40 40 $request->setCookie('phusr', $user->getUsername()); 41 41 $request->setCookie('phsid', $session_key); 42 + 43 + // Clear the registration key. 42 44 $request->clearCookie('phreg'); 45 + 46 + // Clear the client ID / OAuth state key. 47 + $request->clearCookie('phcid'); 43 48 } 44 49 45 50 protected function buildLoginValidateResponse(PhabricatorUser $user) {
+1
src/applications/auth/controller/PhabricatorAuthStartController.php
··· 62 62 63 63 if (!$request->isFormPost()) { 64 64 $request->setCookie('next_uri', $next_uri); 65 + $request->setCookie('phcid', Filesystem::readRandomCharacters(16)); 65 66 } 66 67 67 68 $out = array();
+24 -1
src/applications/auth/provider/PhabricatorAuthProviderOAuth.php
··· 67 67 $panel->appendChild($form); 68 68 69 69 $adapter = $this->getAdapter(); 70 - 70 + $adapter->setState(PhabricatorHash::digest($request->getCookie('phcid'))); 71 71 72 72 $uri = new PhutilURI($adapter->getAuthenticateURI()); 73 73 $params = $uri->getQueryParams(); ··· 111 111 'response.')); 112 112 113 113 return array($account, $response); 114 + } 115 + 116 + if ($adapter->supportsStateParameter()) { 117 + $phcid = $request->getCookie('phcid'); 118 + if (!strlen($phcid)) { 119 + $response = $controller->buildProviderErrorResponse( 120 + $this, 121 + pht( 122 + 'Your browser did not submit a "phcid" cookie with OAuth state '. 123 + 'information in the request. Check that cookies are enabled. '. 124 + 'If this problem persists, you may need to clear your cookies.')); 125 + } 126 + 127 + $state = $request->getStr('state'); 128 + $expect = PhabricatorHash::digest($phcid); 129 + if ($state !== $expect) { 130 + $response = $controller->buildProviderErrorResponse( 131 + $this, 132 + pht( 133 + 'The OAuth provider did not return the correct "state" parameter '. 134 + 'in its response. If this problem persists, you may need to clear '. 135 + 'your cookies.')); 136 + } 114 137 } 115 138 116 139 $adapter->setCode($code);