Spaces:
No application file
No application file
| namespace Mautic\PluginBundle\Helper; | |
| use Mautic\PluginBundle\Integration\UnifiedIntegrationInterface; | |
| use Symfony\Component\HttpFoundation\Request; | |
| /** | |
| * Portions modified from https://code.google.com/p/simple-php-oauth/. | |
| */ | |
| class oAuthHelper | |
| { | |
| private $clientId; | |
| private $clientSecret; | |
| private $accessToken; | |
| private $accessTokenSecret; | |
| private $callback; | |
| private $settings; | |
| public function __construct( | |
| UnifiedIntegrationInterface $integration, | |
| private ?Request $request = null, | |
| $settings = [] | |
| ) { | |
| $clientId = $integration->getClientIdKey(); | |
| $clientSecret = $integration->getClientSecretKey(); | |
| $keys = $integration->getDecryptedApiKeys(); | |
| $this->clientId = $keys[$clientId] ?? null; | |
| $this->clientSecret = $keys[$clientSecret] ?? null; | |
| $authToken = $integration->getAuthTokenKey(); | |
| $this->accessToken = $keys[$authToken] ?? ''; | |
| $this->accessTokenSecret = $settings['token_secret'] ?? ''; | |
| $this->callback = $integration->getAuthCallbackUrl(); | |
| $this->settings = $settings; | |
| } | |
| public function getAuthorizationHeader($url, $parameters, $method): array | |
| { | |
| // Get standard OAuth headers | |
| $headers = $this->getOauthHeaders(); | |
| if (!empty($this->settings['include_verifier']) && $this->request && $this->request->query->has('oauth_verifier')) { | |
| $headers['oauth_verifier'] = $this->request->query->get('oauth_verifier'); | |
| } | |
| if (!empty($this->settings['query'])) { | |
| // Include query in the base string if appended | |
| $parameters = array_merge($parameters, $this->settings['query']); | |
| } | |
| if (!empty($this->settings['double_encode_basestring_parameters'])) { | |
| // Parameters must be encoded before going through buildBaseString | |
| array_walk($parameters, function (&$val, $key, $oauth): void { | |
| $val = $oauth->encode($val); | |
| }, $this); | |
| } | |
| $signature = array_merge($headers, $parameters); | |
| $base_info = $this->buildBaseString($url, $method, $signature); | |
| $composite_key = $this->getCompositeKey(); | |
| $headers['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true)); | |
| return [$this->buildAuthorizationHeader($headers), 'Expect:']; | |
| } | |
| /** | |
| * Get composite key for OAuth 1 signature signing. | |
| */ | |
| private function getCompositeKey(): string | |
| { | |
| if (strlen($this->accessTokenSecret) > 0) { | |
| $composite_key = $this->encode($this->clientSecret).'&'.$this->encode($this->accessTokenSecret); | |
| } else { | |
| $composite_key = $this->encode($this->clientSecret).'&'; | |
| } | |
| return $composite_key; | |
| } | |
| /** | |
| * Get OAuth 1.0 Headers. | |
| */ | |
| private function getOauthHeaders(): array | |
| { | |
| $oauth = [ | |
| 'oauth_consumer_key' => $this->clientId, | |
| 'oauth_nonce' => $this->generateNonce(), | |
| 'oauth_signature_method' => 'HMAC-SHA1', | |
| 'oauth_timestamp' => time(), | |
| 'oauth_version' => '1.0', | |
| ]; | |
| if (empty($this->settings['authorize_session']) && !empty($this->accessToken)) { | |
| $oauth['oauth_token'] = $this->accessToken; | |
| } elseif (!empty($this->settings['request_token'])) { | |
| // OAuth1.a access_token request that requires the retrieved request_token to be appended | |
| $oauth['oauth_token'] = $this->settings['request_token']; | |
| } | |
| if (!empty($this->settings['append_callback']) && !empty($this->callback)) { | |
| $oauth['oauth_callback'] = urlencode($this->callback); | |
| } | |
| return $oauth; | |
| } | |
| /** | |
| * Build base string for OAuth 1 signature signing. | |
| */ | |
| private function buildBaseString($baseURI, $method, $params): string | |
| { | |
| $r = $this->normalizeParameters($params); | |
| return $method.'&'.$this->encode($baseURI).'&'.$this->encode($r); | |
| } | |
| /** | |
| * Build header for OAuth 1 authorization. | |
| */ | |
| private function buildAuthorizationHeader($oauth): string | |
| { | |
| $r = 'Authorization: OAuth '; | |
| $values = $this->normalizeParameters($oauth, true, true); | |
| return $r.implode(', ', $values); | |
| } | |
| /** | |
| * Normalize parameters. | |
| * | |
| * @param bool $encode | |
| * @param bool $returnarray | |
| * | |
| * @return string|array<string,string> | |
| */ | |
| private function normalizeParameters($parameters, $encode = false, $returnarray = false, $normalized = [], $key = '') | |
| { | |
| // Sort by key | |
| ksort($parameters); | |
| foreach ($parameters as $k => $v) { | |
| if (is_array($v)) { | |
| $normalized = $this->normalizeParameters($v, $encode, true, $normalized, $k); | |
| } else { | |
| if ($key) { | |
| // Multidimensional array; using foo=baz&foo=bar rather than foo[bar]=baz&foo[baz]=bar as this is | |
| // what the server expects when creating the signature | |
| $k = $key; | |
| } | |
| if ($encode) { | |
| $normalized[] = $this->encode($k).'="'.$this->encode($v).'"'; | |
| } else { | |
| $normalized[] = $k.'='.$v; | |
| } | |
| } | |
| } | |
| return $returnarray ? $normalized : implode('&', $normalized); | |
| } | |
| /** | |
| * Returns an encoded string according to the RFC3986. | |
| */ | |
| public function encode($string): string | |
| { | |
| return str_replace('%7E', '~', rawurlencode($string)); | |
| } | |
| /** | |
| * OAuth1.0 nonce generator. | |
| * | |
| * @param int $bits | |
| */ | |
| private function generateNonce($bits = 64): string | |
| { | |
| $result = ''; | |
| $accumulatedBits = 0; | |
| $random = mt_getrandmax(); | |
| for ($totalBits = 0; 0 != $random; $random >>= 1) { | |
| ++$totalBits; | |
| } | |
| $usableBits = intval($totalBits / 8) * 8; | |
| while ($accumulatedBits < $bits) { | |
| $bitsToAdd = min($totalBits - $usableBits, $bits - $accumulatedBits); | |
| if (0 != $bitsToAdd % 4) { | |
| // add bits in whole increments of 4 | |
| $bitsToAdd += 4 - $bitsToAdd % 4; | |
| } | |
| // isolate leftmost $bits_to_add from mt_rand() result | |
| $moreBits = mt_rand() & ((1 << $bitsToAdd) - 1); | |
| // format as hex (this will be safe) | |
| $format_string = '%0'.($bitsToAdd / 4).'x'; | |
| $result .= sprintf($format_string, $moreBits); | |
| $accumulatedBits += $bitsToAdd; | |
| } | |
| return $result; | |
| } | |
| } | |