4 * Abstract adapter for OAuth1 providers.
6 abstract class PhutilOAuth1AuthAdapter
extends PhutilAuthAdapter
{
9 private $consumerSecret;
13 private $handshakeData;
17 public function setPrivateKey(PhutilOpaqueEnvelope
$private_key) {
18 $this->privateKey
= $private_key;
22 public function getPrivateKey() {
23 return $this->privateKey
;
26 public function setCallbackURI($callback_uri) {
27 $this->callbackURI
= $callback_uri;
31 public function getCallbackURI() {
32 return $this->callbackURI
;
35 public function setVerifier($verifier) {
36 $this->verifier
= $verifier;
40 public function getVerifier() {
41 return $this->verifier
;
44 public function setConsumerSecret(PhutilOpaqueEnvelope
$consumer_secret) {
45 $this->consumerSecret
= $consumer_secret;
49 public function getConsumerSecret() {
50 return $this->consumerSecret
;
53 public function setConsumerKey($consumer_key) {
54 $this->consumerKey
= $consumer_key;
58 public function getConsumerKey() {
59 return $this->consumerKey
;
62 public function setTokenSecret($token_secret) {
63 $this->tokenSecret
= $token_secret;
67 public function getTokenSecret() {
68 return $this->tokenSecret
;
71 public function setToken($token) {
72 $this->token
= $token;
76 public function getToken() {
80 protected function getHandshakeData() {
81 if ($this->handshakeData
=== null) {
82 $this->finishOAuthHandshake();
84 return $this->handshakeData
;
87 abstract protected function getRequestTokenURI();
88 abstract protected function getAuthorizeTokenURI();
89 abstract protected function getValidateTokenURI();
91 protected function getSignatureMethod() {
95 public function getContentSecurityPolicyFormActions() {
97 $this->getAuthorizeTokenURI(),
101 protected function newOAuth1Future($uri, $data = array()) {
102 $future = id(new PhutilOAuth1Future($uri, $data))
104 ->setSignatureMethod($this->getSignatureMethod());
106 $consumer_key = $this->getConsumerKey();
107 if (strlen($consumer_key)) {
108 $future->setConsumerKey($consumer_key);
113 'setConsumerKey()'));
116 $consumer_secret = $this->getConsumerSecret();
117 if ($consumer_secret) {
118 $future->setConsumerSecret($consumer_secret);
121 if (strlen($this->getToken())) {
122 $future->setToken($this->getToken());
125 if (strlen($this->getTokenSecret())) {
126 $future->setTokenSecret($this->getTokenSecret());
129 if ($this->getPrivateKey()) {
130 $future->setPrivateKey($this->getPrivateKey());
136 public function getClientRedirectURI() {
137 $request_token_uri = $this->getRequestTokenURI();
139 $future = $this->newOAuth1Future($request_token_uri);
140 if (strlen($this->getCallbackURI())) {
141 $future->setCallbackURI($this->getCallbackURI());
144 list($body) = $future->resolvex();
145 $data = id(new PhutilQueryStringParser())->parseQueryString($body);
147 // NOTE: Per the spec, this value MUST be the string 'true'.
148 $confirmed = idx($data, 'oauth_callback_confirmed');
149 if ($confirmed !== 'true') {
151 pht("Expected '%s' to be '%s'!", 'oauth_callback_confirmed', 'true'));
154 $this->readTokenAndTokenSecret($data);
156 $authorize_token_uri = new PhutilURI($this->getAuthorizeTokenURI());
157 $authorize_token_uri->replaceQueryParam('oauth_token', $this->getToken());
159 return phutil_string_cast($authorize_token_uri);
162 protected function finishOAuthHandshake() {
163 $this->willFinishOAuthHandshake();
165 if (!$this->getToken()) {
166 throw new Exception(pht('Expected token to finish OAuth handshake!'));
168 if (!$this->getVerifier()) {
169 throw new Exception(pht('Expected verifier to finish OAuth handshake!'));
172 $validate_uri = $this->getValidateTokenURI();
174 'oauth_verifier' => $this->getVerifier(),
177 list($body) = $this->newOAuth1Future($validate_uri, $params)->resolvex();
178 $data = id(new PhutilQueryStringParser())->parseQueryString($body);
180 $this->readTokenAndTokenSecret($data);
182 $this->handshakeData
= $data;
185 private function readTokenAndTokenSecret(array $data) {
186 $token = idx($data, 'oauth_token');
188 throw new Exception(pht("Expected '%s' in response!", 'oauth_token'));
191 $token_secret = idx($data, 'oauth_token_secret');
192 if (!$token_secret) {
194 pht("Expected '%s' in response!", 'oauth_token_secret'));
197 $this->setToken($token);
198 $this->setTokenSecret($token_secret);
204 * Hook that allows subclasses to take actions before the OAuth handshake
207 protected function willFinishOAuthHandshake() {