Page MenuHome GnuPG

No OneTemporary

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

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

Event Timeline