Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/future/PhabricatorDuoFuture.php
- This file was added.
| <?php | |||||
| final class PhabricatorDuoFuture | |||||
| extends FutureProxy { | |||||
| private $future; | |||||
| private $integrationKey; | |||||
| private $secretKey; | |||||
| private $apiHostname; | |||||
| private $httpMethod = 'POST'; | |||||
| private $method; | |||||
| private $parameters; | |||||
| private $timeout; | |||||
| public function __construct() { | |||||
| parent::__construct(null); | |||||
| } | |||||
| public function setIntegrationKey($integration_key) { | |||||
| $this->integrationKey = $integration_key; | |||||
| return $this; | |||||
| } | |||||
| public function setSecretKey(PhutilOpaqueEnvelope $key) { | |||||
| $this->secretKey = $key; | |||||
| return $this; | |||||
| } | |||||
| public function setAPIHostname($hostname) { | |||||
| $this->apiHostname = $hostname; | |||||
| return $this; | |||||
| } | |||||
| public function setMethod($method, array $parameters) { | |||||
| $this->method = $method; | |||||
| $this->parameters = $parameters; | |||||
| return $this; | |||||
| } | |||||
| public function setTimeout($timeout) { | |||||
| $this->timeout = $timeout; | |||||
| return $this; | |||||
| } | |||||
| public function getTimeout() { | |||||
| return $this->timeout; | |||||
| } | |||||
| public function setHTTPMethod($method) { | |||||
| $this->httpMethod = $method; | |||||
| return $this; | |||||
| } | |||||
| public function getHTTPMethod() { | |||||
| return $this->httpMethod; | |||||
| } | |||||
| protected function getProxiedFuture() { | |||||
| if (!$this->future) { | |||||
| if ($this->integrationKey === null) { | |||||
| throw new PhutilInvalidStateException('setIntegrationKey'); | |||||
| } | |||||
| if ($this->secretKey === null) { | |||||
| throw new PhutilInvalidStateException('setSecretKey'); | |||||
| } | |||||
| if ($this->apiHostname === null) { | |||||
| throw new PhutilInvalidStateException('setAPIHostname'); | |||||
| } | |||||
| if ($this->method === null || $this->parameters === null) { | |||||
| throw new PhutilInvalidStateException('setMethod'); | |||||
| } | |||||
| $path = (string)urisprintf('/auth/v2/%s', $this->method); | |||||
| $host = $this->apiHostname; | |||||
| $host = phutil_utf8_strtolower($host); | |||||
| $uri = id(new PhutilURI('')) | |||||
| ->setProtocol('https') | |||||
| ->setDomain($host) | |||||
| ->setPath($path); | |||||
| $data = $this->parameters; | |||||
| $date = date('r'); | |||||
| $http_method = $this->getHTTPMethod(); | |||||
| ksort($data); | |||||
| $data_parts = array(); | |||||
| foreach ($data as $key => $value) { | |||||
| $data_parts[] = rawurlencode($key).'='.rawurlencode($value); | |||||
| } | |||||
| $data_parts = implode('&', $data_parts); | |||||
| $corpus = array( | |||||
| $date, | |||||
| $http_method, | |||||
| $host, | |||||
| $path, | |||||
| $data_parts, | |||||
| ); | |||||
| $corpus = implode("\n", $corpus); | |||||
| $signature = hash_hmac( | |||||
| 'sha1', | |||||
| $corpus, | |||||
| $this->secretKey->openEnvelope()); | |||||
| $signature = new PhutilOpaqueEnvelope($signature); | |||||
| $future = id(new HTTPSFuture($uri, $data)) | |||||
| ->setHTTPBasicAuthCredentials($this->integrationKey, $signature) | |||||
| ->setMethod($http_method) | |||||
| ->addHeader('Accept', 'application/json') | |||||
| ->addHeader('Date', $date); | |||||
| $timeout = $this->getTimeout(); | |||||
| if ($timeout) { | |||||
| $future->setTimeout($timeout); | |||||
| } | |||||
| $this->future = $future; | |||||
| } | |||||
| return $this->future; | |||||
| } | |||||
| protected function didReceiveResult($result) { | |||||
| list($status, $body, $headers) = $result; | |||||
| if ($status->isError()) { | |||||
| throw $status; | |||||
| } | |||||
| try { | |||||
| $data = phutil_json_decode($body); | |||||
| } catch (PhutilJSONParserException $ex) { | |||||
| throw new PhutilProxyException( | |||||
| pht('Expected JSON response from Duo.'), | |||||
| $ex); | |||||
| } | |||||
| return $data; | |||||
| } | |||||
| } | |||||