@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.

at upstream/main 213 lines 5.4 kB view raw
1<?php 2 3/** 4 * Abstract adapter for OAuth1 providers. 5 */ 6abstract class PhutilOAuth1AuthAdapter extends PhutilAuthAdapter { 7 8 private $consumerKey; 9 private $consumerSecret; 10 private $token; 11 private $tokenSecret; 12 private $verifier; 13 private $handshakeData; 14 private $callbackURI; 15 private $privateKey; 16 17 public function setPrivateKey(PhutilOpaqueEnvelope $private_key) { 18 $this->privateKey = $private_key; 19 return $this; 20 } 21 22 public function getPrivateKey() { 23 return $this->privateKey; 24 } 25 26 public function setCallbackURI($callback_uri) { 27 $this->callbackURI = $callback_uri; 28 return $this; 29 } 30 31 public function getCallbackURI() { 32 return $this->callbackURI; 33 } 34 35 public function setVerifier($verifier) { 36 $this->verifier = $verifier; 37 return $this; 38 } 39 40 public function getVerifier() { 41 return $this->verifier; 42 } 43 44 public function setConsumerSecret(PhutilOpaqueEnvelope $consumer_secret) { 45 $this->consumerSecret = $consumer_secret; 46 return $this; 47 } 48 49 public function getConsumerSecret() { 50 return $this->consumerSecret; 51 } 52 53 public function setConsumerKey($consumer_key) { 54 $this->consumerKey = $consumer_key; 55 return $this; 56 } 57 58 public function getConsumerKey() { 59 return $this->consumerKey; 60 } 61 62 public function setTokenSecret($token_secret) { 63 $this->tokenSecret = $token_secret; 64 return $this; 65 } 66 67 public function getTokenSecret() { 68 return $this->tokenSecret; 69 } 70 71 public function setToken($token) { 72 $this->token = $token; 73 return $this; 74 } 75 76 public function getToken() { 77 return $this->token; 78 } 79 80 protected function getHandshakeData() { 81 if ($this->handshakeData === null) { 82 $this->finishOAuthHandshake(); 83 } 84 return $this->handshakeData; 85 } 86 87 abstract protected function getRequestTokenURI(); 88 abstract protected function getAuthorizeTokenURI(); 89 abstract protected function getValidateTokenURI(); 90 91 protected function getSignatureMethod() { 92 return 'HMAC-SHA1'; 93 } 94 95 public function getContentSecurityPolicyFormActions() { 96 return array( 97 $this->getAuthorizeTokenURI(), 98 ); 99 } 100 101 protected function newOAuth1Future($uri, $data = array()) { 102 $future = id(new PhutilOAuth1Future($uri, $data)) 103 ->addHeader('User-Agent', 104 PhabricatorEnv::getEnvConfig('phabricator.base-uri')) 105 ->setMethod('POST') 106 ->setSignatureMethod($this->getSignatureMethod()); 107 108 $consumer_key = $this->getConsumerKey(); 109 if (phutil_nonempty_string($consumer_key)) { 110 $future->setConsumerKey($consumer_key); 111 } else { 112 throw new Exception( 113 pht( 114 '%s is required!', 115 'setConsumerKey()')); 116 } 117 118 $consumer_secret = $this->getConsumerSecret(); 119 if ($consumer_secret) { 120 $future->setConsumerSecret($consumer_secret); 121 } 122 123 if (phutil_nonempty_string($this->getToken())) { 124 $future->setToken($this->getToken()); 125 } 126 127 if (phutil_nonempty_string($this->getTokenSecret())) { 128 $future->setTokenSecret($this->getTokenSecret()); 129 } 130 131 if ($this->getPrivateKey()) { 132 $future->setPrivateKey($this->getPrivateKey()); 133 } 134 135 return $future; 136 } 137 138 public function getClientRedirectURI() { 139 $request_token_uri = $this->getRequestTokenURI(); 140 141 $future = $this->newOAuth1Future($request_token_uri); 142 if (phutil_nonempty_string($this->getCallbackURI())) { 143 $future->setCallbackURI($this->getCallbackURI()); 144 } 145 146 list($body) = $future->resolvex(); 147 $data = id(new PhutilQueryStringParser())->parseQueryString($body); 148 149 // NOTE: Per the spec, this value MUST be the string 'true'. 150 $confirmed = idx($data, 'oauth_callback_confirmed'); 151 if ($confirmed !== 'true') { 152 throw new Exception( 153 pht("Expected '%s' to be '%s'!", 'oauth_callback_confirmed', 'true')); 154 } 155 156 $this->readTokenAndTokenSecret($data); 157 158 $authorize_token_uri = new PhutilURI($this->getAuthorizeTokenURI()); 159 $authorize_token_uri->replaceQueryParam('oauth_token', $this->getToken()); 160 161 return phutil_string_cast($authorize_token_uri); 162 } 163 164 protected function finishOAuthHandshake() { 165 $this->willFinishOAuthHandshake(); 166 167 if (!$this->getToken()) { 168 throw new Exception(pht('Expected token to finish OAuth handshake!')); 169 } 170 if (!$this->getVerifier()) { 171 throw new Exception(pht('Expected verifier to finish OAuth handshake!')); 172 } 173 174 $validate_uri = $this->getValidateTokenURI(); 175 $params = array( 176 'oauth_verifier' => $this->getVerifier(), 177 ); 178 179 list($body) = $this->newOAuth1Future($validate_uri, $params)->resolvex(); 180 $data = id(new PhutilQueryStringParser())->parseQueryString($body); 181 182 $this->readTokenAndTokenSecret($data); 183 184 $this->handshakeData = $data; 185 } 186 187 private function readTokenAndTokenSecret(array $data) { 188 $token = idx($data, 'oauth_token'); 189 if (!$token) { 190 throw new Exception(pht("Expected '%s' in response!", 'oauth_token')); 191 } 192 193 $token_secret = idx($data, 'oauth_token_secret'); 194 if (!$token_secret) { 195 throw new Exception( 196 pht("Expected '%s' in response!", 'oauth_token_secret')); 197 } 198 199 $this->setToken($token); 200 $this->setTokenSecret($token_secret); 201 202 return $this; 203 } 204 205 /** 206 * Hook that allows subclasses to take actions before the OAuth handshake 207 * is completed. 208 */ 209 protected function willFinishOAuthHandshake() { 210 return; 211 } 212 213}