Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36623405
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
21 KB
Subscribers
None
View Options
diff --git a/src/auth/PhutilAuthAdapterOAuth1.php b/src/auth/PhutilAuthAdapterOAuth1.php
index 996523f..26be5be 100644
--- a/src/auth/PhutilAuthAdapterOAuth1.php
+++ b/src/auth/PhutilAuthAdapterOAuth1.php
@@ -1,188 +1,188 @@
<?php
abstract class PhutilAuthAdapterOAuth1 extends PhutilAuthAdapter {
private $consumerKey;
private $consumerSecret;
private $token;
private $tokenSecret;
private $verifier;
private $handshakeData;
private $callbackURI;
private $privateKey;
public function setPrivateKey(PhutilOpaqueEnvelope $private_key) {
$this->privateKey = $private_key;
return $this;
}
public function getPrivateKey() {
return $this->privateKey;
}
public function setCallbackURI($callback_uri) {
$this->callbackURI = $callback_uri;
return $this;
}
public function getCallbackURI() {
return $this->callbackURI;
}
public function setVerifier($verifier) {
$this->verifier = $verifier;
return $this;
}
public function getVerifier() {
return $this->verifier;
}
- public function setConsumerSecret($consumer_secret) {
+ public function setConsumerSecret(PhutilOpaqueEnvelope $consumer_secret) {
$this->consumerSecret = $consumer_secret;
return $this;
}
public function getConsumerSecret() {
return $this->consumerSecret;
}
public function setConsumerKey($consumer_key) {
$this->consumerKey = $consumer_key;
return $this;
}
public function getConsumerKey() {
return $this->consumerKey;
}
public function setTokenSecret($token_secret) {
$this->tokenSecret = $token_secret;
return $this;
}
public function getTokenSecret() {
return $this->tokenSecret;
}
public function setToken($token) {
$this->token = $token;
return $this;
}
public function getToken() {
return $this->token;
}
protected function getHandshakeData() {
if ($this->handshakeData === null) {
$this->finishOAuthHandshake();
}
return $this->handshakeData;
}
abstract protected function getRequestTokenURI();
abstract protected function getAuthorizeTokenURI();
abstract protected function getValidateTokenURI();
protected function getSignatureMethod() {
return 'HMAC-SHA1';
}
protected function newOAuth1Future($uri, $data = array()) {
$future = id(new PhutilOAuth1Future($uri, $data))
->setMethod('POST')
->setSignatureMethod($this->getSignatureMethod());
$consumer_key = $this->getConsumerKey();
if (strlen($consumer_key)) {
$future->setConsumerKey($consumer_key);
} else {
throw new Exception("setConsumerKey() is required!");
}
$consumer_secret = $this->getConsumerSecret();
- if (strlen($consumer_secret)) {
+ if ($consumer_secret) {
$future->setConsumerSecret($consumer_secret);
}
if (strlen($this->getToken())) {
$future->setToken($this->getToken());
}
if (strlen($this->getTokenSecret())) {
- $future->setToken($this->getTokenSecret());
+ $future->setTokenSecret($this->getTokenSecret());
}
if ($this->getPrivateKey()) {
$future->setPrivateKey($this->getPrivateKey());
}
return $future;
}
public function getClientRedirectURI() {
$request_token_uri = $this->getRequestTokenURI();
$future = $this->newOAuth1Future($request_token_uri);
if (strlen($this->getCallbackURI())) {
$future->setCallbackURI($this->getCallbackURI());
}
list($body) = $future->resolvex();
$data = id(new PhutilQueryStringParser())->parseQueryString($body);
// NOTE: Per the spec, this value MUST be the string 'true'.
$confirmed = idx($data, 'oauth_callback_confirmed');
if ($confirmed !== "true") {
throw new Exception(
"Expected 'oauth_callback_confirmed' to be 'true'!");
}
$this->readTokenAndTokenSecret($data);
$authorize_token_uri = new PhutilURI($this->getAuthorizeTokenURI());
$authorize_token_uri->setQueryParam('oauth_token', $this->getToken());
return (string)$authorize_token_uri;
}
protected function finishOAuthHandshake() {
if (!$this->getToken()) {
throw new Exception("Expected token to finish OAuth handshake!");
}
if (!$this->getVerifier()) {
throw new Exception("Expected verifier to finish OAuth handshake!");
}
$validate_uri = $this->getValidateTokenURI();
$params = array(
'oauth_verifier' => $this->getVerifier(),
);
list($body) = $this->newOAuth1Future($validate_uri, $params)->resolvex();
$data = id(new PhutilQueryStringParser())->parseQueryString($body);
$this->readTokenAndTokenSecret($data);
$this->handshakeData = $data;
}
private function readTokenAndTokenSecret(array $data) {
$token = idx($data, 'oauth_token');
if (!$token) {
throw new Exception("Expected 'oauth_token' in response!");
}
$token_secret = idx($data, 'oauth_token_secret');
if (!$token_secret) {
throw new Exception("Expected 'oauth_token_secret' in response!");
}
$this->setToken($token);
$this->setTokenSecret($token_secret);
return $this;
}
}
diff --git a/src/auth/PhutilAuthAdapterOAuthTwitter.php b/src/auth/PhutilAuthAdapterOAuthTwitter.php
index e13f8c1..c127eef 100644
--- a/src/auth/PhutilAuthAdapterOAuthTwitter.php
+++ b/src/auth/PhutilAuthAdapterOAuthTwitter.php
@@ -1,29 +1,77 @@
<?php
final class PhutilAuthAdapterOAuthTwitter extends PhutilAuthAdapterOAuth1 {
+ private $userInfo;
+
public function getAccountID() {
return idx($this->getHandshakeData(), 'user_id');
}
+ public function getAccountName() {
+ return idx($this->getHandshakeData(), 'screen_name');
+ }
+
+ public function getAccountURI() {
+ $name = $this->getAccountName();
+ if (strlen($name)) {
+ return 'https://twitter.com/'.$name;
+ }
+ return null;
+ }
+
+ public function getAccountImageURI() {
+ $info = $this->getUserInfo();
+ return idx($info, 'profile_image_url');
+ }
+
+ public function getAccountRealName() {
+ $info = $this->getUserInfo();
+ return idx($info, 'name');
+ }
+
public function getAdapterType() {
return 'twitter';
}
public function getAdapterDomain() {
return 'twitter.com';
}
protected function getRequestTokenURI() {
return 'https://api.twitter.com/oauth/request_token';
}
protected function getAuthorizeTokenURI() {
return 'https://api.twitter.com/oauth/authorize';
}
protected function getValidateTokenURI() {
return 'https://api.twitter.com/oauth/access_token';
}
+ private function getUserInfo() {
+ if ($this->userInfo === null) {
+
+ $uri = new PhutilURI('https://api.twitter.com/1.1/users/show.json');
+ $uri->setQueryParams(
+ array(
+ 'user_id' => $this->getAccountID(),
+ ));
+
+ list($body) = $this->newOAuth1Future($uri)
+ ->setMethod('GET')
+ ->resolvex();
+
+ $data = json_decode($body, true);
+ if (!is_array($data)) {
+ throw new Exception("Expect JSON, got: {$body}");
+ }
+
+ $this->userInfo = $data;
+ }
+ return $this->userInfo;
+ }
+
+
}
diff --git a/src/future/oauth/PhutilOAuth1Future.php b/src/future/oauth/PhutilOAuth1Future.php
index f3e455a..70c201d 100644
--- a/src/future/oauth/PhutilOAuth1Future.php
+++ b/src/future/oauth/PhutilOAuth1Future.php
@@ -1,234 +1,238 @@
<?php
/**
* Proxy future that implements OAuth1 request signing. For references, see:
*
* RFC 5849: http://tools.ietf.org/html/rfc5849
* Guzzle: https://github.com/guzzle/guzzle/blob/master/src/Guzzle/Plugin/Oauth/OauthPlugin.php
*
*/
final class PhutilOAuth1Future extends FutureProxy {
private $uri;
private $data;
private $consumerKey;
private $consumerSecret;
private $signatureMethod;
private $privateKey;
private $method = 'POST';
private $token;
private $tokenSecret;
private $nonce;
private $timestamp;
private $hasConstructedFuture;
private $callbackURI;
public function setCallbackURI($callback_uri) {
$this->callbackURI = $callback_uri;
return $this;
}
public function setTimestamp($timestamp) {
$this->timestamp = $timestamp;
return $this;
}
public function setNonce($nonce) {
$this->nonce = $nonce;
return $this;
}
public function setTokenSecret($token_secret) {
$this->tokenSecret = $token_secret;
return $this;
}
public function setToken($token) {
$this->token = $token;
return $this;
}
public function setPrivateKey(PhutilOpaqueEnvelope $private_key) {
$this->privateKey = $private_key;
return $this;
}
public function setSignatureMethod($signature_method) {
$this->signatureMethod = $signature_method;
return $this;
}
public function setConsumerKey($consumer_key) {
$this->consumerKey = $consumer_key;
return $this;
}
- public function setConsumerSecret($consumer_secret) {
+ public function setConsumerSecret(PhutilOpaqueEnvelope $consumer_secret) {
$this->consumerSecret = $consumer_secret;
return $this;
}
public function setMethod($method) {
$this->method = $method;
return $this;
}
public function __construct($uri, $data = array()) {
$this->uri = new PhutilURI((string)$uri);
$this->data = $data;
$this->setProxiedFuture(new HTTPSFuture($uri, $data));
}
public function getSignature() {
$params = $this->data
+ $this->uri->getQueryParams()
+ $this->getOAuth1Headers();
return $this->sign($params);
}
public function getProxiedFuture() {
$future = parent::getProxiedFuture();
if (!$this->hasConstructedFuture) {
$future->setMethod($this->method);
$oauth_headers = $this->getOAuth1Headers();
$oauth_headers['oauth_signature'] = $this->getSignature();
$full_oauth_header = array();
foreach ($oauth_headers as $header => $value) {
$full_oauth_header[] = $header.'="'.urlencode($value).'"';
}
$full_oauth_header = 'OAuth '.implode(", ", $full_oauth_header);
$future->addHeader('Authorization', $full_oauth_header);
$this->hasConstructedFuture = true;
}
return $future;
}
protected function didReceiveResult($result) {
return $result;
}
private function getOAuth1Headers() {
if (!$this->nonce) {
$this->nonce = Filesystem::readRandomCharacters(32);
}
if (!$this->timestamp) {
$this->timestamp = time();
}
$oauth_headers = array(
'oauth_consumer_key' => $this->consumerKey,
'oauth_signature_method' => $this->signatureMethod,
'oauth_timestamp' => $this->timestamp,
'oauth_nonce' => $this->nonce,
'oauth_version' => '1.0',
);
if ($this->callbackURI) {
$oauth_headers['oauth_callback'] = (string)$this->callbackURI;
}
if ($this->token) {
$oauth_headers['oauth_token'] = $this->token;
}
return $oauth_headers;
}
private function sign(array $params) {
ksort($params);
$pstr = array();
foreach ($params as $key => $value) {
$pstr[] = rawurlencode($key).'='.rawurlencode($value);
}
$pstr = implode('&', $pstr);
$sign_uri = clone $this->uri;
$sign_uri->setFragment('');
$sign_uri->setQueryParams(array());
$sign_uri->setProtocol(phutil_utf8_strtolower($sign_uri->getProtocol()));
$protocol = $sign_uri->getProtocol();
switch ($protocol) {
case 'http':
if ($sign_uri->getPort() == 80) {
$sign_uri->setPort(null);
}
break;
case 'https':
if ($sign_uri->getPort() == 443) {
$sign_uri->setPort(null);
}
break;
}
$method = rawurlencode(phutil_utf8_strtoupper($this->method));
$sign_uri = rawurlencode((string)$sign_uri);
$pstr = rawurlencode($pstr);
$sign_input = "{$method}&{$sign_uri}&{$pstr}";
-
return $this->signString($sign_input);
}
private function signString($string) {
- $key = urlencode($this->consumerSecret).'&'.urlencode($this->tokenSecret);
+ $consumer_secret = null;
+ if ($this->consumerSecret) {
+ $consumer_secret = $this->consumerSecret->openEnvelope();
+ }
+
+ $key = urlencode($consumer_secret).'&'.urlencode($this->tokenSecret);
switch ($this->signatureMethod) {
case 'HMAC-SHA1':
if (!$this->consumerSecret) {
throw new Exception(
"Signature method 'HMAC-SHA1' requires setConsumerSecret()!");
}
$hash = hash_hmac('sha1', $string, $key, true);
return base64_encode($hash);
case 'RSA-SHA1':
if (!$this->privateKey) {
throw new Exception(
"Signature method 'RSA-SHA1' requires setPrivateKey()!");
}
$cert = @openssl_pkey_get_private($this->privateKey->openEnvelope());
if (!$cert) {
throw new Exception('openssl_pkey_get_private() failed!');
}
$pkey = @openssl_get_privatekey($cert);
if (!$pkey) {
throw new Exception('openssl_get_privatekey() failed!');
}
$signature = null;
$ok = openssl_sign($string, $signature, $pkey, OPENSSL_ALGO_SHA1);
if (!$ok) {
throw new Exception('openssl_sign() failed!');
}
openssl_free_key($pkey);
return base64_encode($signature);
case 'PLAINTEXT':
if (!$this->consumerSecret) {
throw new Exception(
"Signature method 'PLAINTEXT' requires setConsumerSecret()!");
}
return $key;
default:
throw new Exception("Unknown signature method '{$string}'!");
}
}
public function resolvex() {
$result = $this->getProxiedFuture()->resolvex();
return $this->didReceiveResult($result);
}
}
diff --git a/src/future/oauth/__tests__/PhutilOAuth1FutureTestCase.php b/src/future/oauth/__tests__/PhutilOAuth1FutureTestCase.php
index 641aa34..73e6637 100644
--- a/src/future/oauth/__tests__/PhutilOAuth1FutureTestCase.php
+++ b/src/future/oauth/__tests__/PhutilOAuth1FutureTestCase.php
@@ -1,158 +1,159 @@
<?php
final class PhutilOAuth1FutureTestCase extends PhutilTestCase {
public function testOAuth1SigningWithOldSpecExmaples() {
// NOTE: These examples are from an old version of the OAuth 1 spec,
// so they might not be totally accurate.
$uri = 'https://photos.example.net/request_token';
$future = id(new PhutilOAuth1Future($uri))
->setTimestamp(1191242090)
->setNonce('hsu94j3884jdopsl')
->setConsumerKey('dpf43f3p2l4k3l03')
- ->setConsumerSecret('kd94hf93k423kf44')
+ ->setConsumerSecret(new PhutilOpaqueEnvelope('kd94hf93k423kf44'))
->setSignatureMethod('PLAINTEXT');
$this->assertEqual('kd94hf93k423kf44&', $future->getSignature());
$uri = 'http://photos.example.net/photos';
$data = array(
'file' => 'vacation.jpg',
'size' => 'original',
);
$future = id(new PhutilOAuth1Future($uri, $data))
->setMethod('GET')
->setTimestamp(1191242096)
->setNonce('kllo9940pd9333jh')
->setConsumerKey('dpf43f3p2l4k3l03')
- ->setConsumerSecret('kd94hf93k423kf44')
+ ->setConsumerSecret(new PhutilOpaqueEnvelope('kd94hf93k423kf44'))
->setSignatureMethod('HMAC-SHA1')
->setToken('nnch734d00sl2jdk')
->setTokenSecret('pfkkdhi9sl3r4s00');
$this->assertEqual('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $future->getSignature());
}
public function testOAuth1SigningWithTwitterExamples() {
// NOTE: This example is from Twitter.
// https://dev.twitter.com/docs/auth/creating-signature
$uri = 'https://api.twitter.com/1/statuses/update.json?'.
'include_entities=true';
$data = array(
'status' => 'Hello Ladies + Gentlemen, a signed OAuth request!',
);
$future = id(new PhutilOAuth1Future($uri, $data))
->setMethod('POST')
->setConsumerKey('xvz1evFS4wEEPTGEFPHBog')
- ->setConsumerSecret('kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw')
+ ->setConsumerSecret(
+ new PhutilOpaqueEnvelope('kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw'))
->setNonce('kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg')
->setSignatureMethod('HMAC-SHA1')
->setTimestamp(1318622958)
->setToken('370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb')
->setTokenSecret('LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE');
$this->assertEqual('tnnArxj06cWHq44gCs1OSKk/jLY=', $future->getSignature());
}
public function testOAuth1SigningWithJIRAExamples() {
// NOTE: This is an emprically example against JIRA v6.0.6, in that the
// code seems to work when actually authing. It primarily serves as a check
// of the RSA-SHA1 signature method.
$public_key = <<<EOKEY
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz/cLggl8VtHsZAtQudfz
fN14/xZgtUxA/J10jVwaz30etSiTY1QmeUbL09XKM7NyIL432+AbJkLEJ/EF6NIh
XkqrtrDvi+48zcSl0zwHthGjESLve9o0i9m1EjEaztnv8EdaNuXkUtYfEMUm9KEk
iocXTdyLszdtrGOPY1h4qQUrgxO0JY0bBoRa6PqiGe7M/3yvstbW0DGNGvNvLaq7
k54tPCDKWGKphoEQ6wxd5Hk30LEKn0dqZ5i11ZYal4bfj7UkvjiA5bgAAZmyQ1IV
CqzMQsPLwAlw/8xyu9EnCE49odmPKn/cbvY5vhoRwDbHDsOuwEPvoFCV9hoXvWhT
GfWcxDihkgBVDzqHZYgCctTjr+4eZvryBOemPK4FaiEHQ4ZQswX6KT5tW7HcjaQ3
kGz2pgOstLBGu9EN6t4kmFDLFOzWEYM5CfSuaE54pnfNJNXuTER/a1S8NCnjrVtH
/h9B2OoNAIUvyLYMhsL7L/0sr8+Sjnoyg+R3rQZZAEJlAiXLtxjD8HGefNPUe8Md
pEO2GyKD9Z/Vxc5HyIikxqo/+pfjJsOEvbqZg3sHZpTb77+kpCic3CdmXhw8HiXg
KP9BUSF1iTShnz72zMDDws9t4O3EVFVNLH3Imty8uW1KtSzQbfXO1yNFlZXrn4fy
54Bwm3hGUO1PNaWg+4F2J8ECAwEAAQ==
-----END PUBLIC KEY-----
EOKEY;
$private_key = <<<EOKEY
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
EOKEY;
$uri = 'http://local.aphront.com:8090/plugins/servlet/oauth/request-token';
$data = array();
$future = id(new PhutilOAuth1Future($uri, $data))
->setConsumerKey('quackquack')
->setPrivateKey(new PhutilOpaqueEnvelope($private_key))
->setTimestamp('1375984131')
->setNonce('iamaduck')
->setSignatureMethod('RSA-SHA1');
// The actual signature is 684 bytes and begins "QwigfVxpOm0AKoWJkFRwbyseso
// VJobhiXpyY0J79Kzki+vwlT4Xz2Tr4vlwDLsra5gJbfdeme4qJ2rE..."
$this->assertEqual(
'5e63e65237e2b8078426996d5ef1a706',
md5($future->getSignature()));
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 26, 6:51 PM (12 h, 6 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
16/98/6cfd18940c8b79d8a8b27f9787ea
Attached To
rPHUTIL libphutil
Event Timeline
Log In to Comment