CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.8 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.8
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • Basic
  • Digest
  • Oauth
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * Redistributions of files must retain the above copyright notice.
  8:  *
  9:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 10:  * @link          https://cakephp.org CakePHP(tm) Project
 11:  * @since         3.0.0
 12:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 13:  */
 14: namespace Cake\Http\Client\Auth;
 15: 
 16: use Cake\Core\Exception\Exception;
 17: use Cake\Http\Client\Request;
 18: use Cake\Utility\Security;
 19: use RuntimeException;
 20: 
 21: /**
 22:  * Oauth 1 authentication strategy for Cake\Http\Client
 23:  *
 24:  * This object does not handle getting Oauth access tokens from the service
 25:  * provider. It only handles make client requests *after* you have obtained the Oauth
 26:  * tokens.
 27:  *
 28:  * Generally not directly constructed, but instead used by Cake\Http\Client
 29:  * when $options['auth']['type'] is 'oauth'
 30:  */
 31: class Oauth
 32: {
 33:     /**
 34:      * Add headers for Oauth authorization.
 35:      *
 36:      * @param \Cake\Http\Client\Request $request The request object.
 37:      * @param array $credentials Authentication credentials.
 38:      * @return \Cake\Http\Client\Request The updated request.
 39:      * @throws \Cake\Core\Exception\Exception On invalid signature types.
 40:      */
 41:     public function authentication(Request $request, array $credentials)
 42:     {
 43:         if (!isset($credentials['consumerKey'])) {
 44:             return $request;
 45:         }
 46:         if (empty($credentials['method'])) {
 47:             $credentials['method'] = 'hmac-sha1';
 48:         }
 49:         $credentials['method'] = strtoupper($credentials['method']);
 50: 
 51:         $value = null;
 52:         switch ($credentials['method']) {
 53:             case 'HMAC-SHA1':
 54:                 $hasKeys = isset(
 55:                     $credentials['consumerSecret'],
 56:                     $credentials['token'],
 57:                     $credentials['tokenSecret']
 58:                 );
 59:                 if (!$hasKeys) {
 60:                     return $request;
 61:                 }
 62:                 $value = $this->_hmacSha1($request, $credentials);
 63:                 break;
 64: 
 65:             case 'RSA-SHA1':
 66:                 if (!isset($credentials['privateKey'])) {
 67:                     return $request;
 68:                 }
 69:                 $value = $this->_rsaSha1($request, $credentials);
 70:                 break;
 71: 
 72:             case 'PLAINTEXT':
 73:                 $hasKeys = isset(
 74:                     $credentials['consumerSecret'],
 75:                     $credentials['token'],
 76:                     $credentials['tokenSecret']
 77:                 );
 78:                 if (!$hasKeys) {
 79:                     return $request;
 80:                 }
 81:                 $value = $this->_plaintext($request, $credentials);
 82:                 break;
 83: 
 84:             default:
 85:                 throw new Exception(sprintf('Unknown Oauth signature method %s', $credentials['method']));
 86:         }
 87: 
 88:         return $request->withHeader('Authorization', $value);
 89:     }
 90: 
 91:     /**
 92:      * Plaintext signing
 93:      *
 94:      * This method is **not** suitable for plain HTTP.
 95:      * You should only ever use PLAINTEXT when dealing with SSL
 96:      * services.
 97:      *
 98:      * @param \Cake\Http\Client\Request $request The request object.
 99:      * @param array $credentials Authentication credentials.
100:      * @return string Authorization header.
101:      */
102:     protected function _plaintext($request, $credentials)
103:     {
104:         $values = [
105:             'oauth_version' => '1.0',
106:             'oauth_nonce' => uniqid(),
107:             'oauth_timestamp' => time(),
108:             'oauth_signature_method' => 'PLAINTEXT',
109:             'oauth_token' => $credentials['token'],
110:             'oauth_consumer_key' => $credentials['consumerKey'],
111:         ];
112:         if (isset($credentials['realm'])) {
113:             $values['oauth_realm'] = $credentials['realm'];
114:         }
115:         $key = [$credentials['consumerSecret'], $credentials['tokenSecret']];
116:         $key = implode('&', $key);
117:         $values['oauth_signature'] = $key;
118: 
119:         return $this->_buildAuth($values);
120:     }
121: 
122:     /**
123:      * Use HMAC-SHA1 signing.
124:      *
125:      * This method is suitable for plain HTTP or HTTPS.
126:      *
127:      * @param \Cake\Http\Client\Request $request The request object.
128:      * @param array $credentials Authentication credentials.
129:      * @return string
130:      */
131:     protected function _hmacSha1($request, $credentials)
132:     {
133:         $nonce = isset($credentials['nonce']) ? $credentials['nonce'] : uniqid();
134:         $timestamp = isset($credentials['timestamp']) ? $credentials['timestamp'] : time();
135:         $values = [
136:             'oauth_version' => '1.0',
137:             'oauth_nonce' => $nonce,
138:             'oauth_timestamp' => $timestamp,
139:             'oauth_signature_method' => 'HMAC-SHA1',
140:             'oauth_token' => $credentials['token'],
141:             'oauth_consumer_key' => $credentials['consumerKey'],
142:         ];
143:         $baseString = $this->baseString($request, $values);
144: 
145:         if (isset($credentials['realm'])) {
146:             $values['oauth_realm'] = $credentials['realm'];
147:         }
148:         $key = [$credentials['consumerSecret'], $credentials['tokenSecret']];
149:         $key = array_map([$this, '_encode'], $key);
150:         $key = implode('&', $key);
151: 
152:         $values['oauth_signature'] = base64_encode(
153:             hash_hmac('sha1', $baseString, $key, true)
154:         );
155: 
156:         return $this->_buildAuth($values);
157:     }
158: 
159:     /**
160:      * Use RSA-SHA1 signing.
161:      *
162:      * This method is suitable for plain HTTP or HTTPS.
163:      *
164:      * @param \Cake\Http\Client\Request $request The request object.
165:      * @param array $credentials Authentication credentials.
166:      * @return string
167:      *
168:      * @throws \RuntimeException
169:      */
170:     protected function _rsaSha1($request, $credentials)
171:     {
172:         if (!function_exists('openssl_pkey_get_private')) {
173:             throw new RuntimeException('RSA-SHA1 signature method requires the OpenSSL extension.');
174:         }
175: 
176:         $nonce = isset($credentials['nonce']) ? $credentials['nonce'] : bin2hex(Security::randomBytes(16));
177:         $timestamp = isset($credentials['timestamp']) ? $credentials['timestamp'] : time();
178:         $values = [
179:             'oauth_version' => '1.0',
180:             'oauth_nonce' => $nonce,
181:             'oauth_timestamp' => $timestamp,
182:             'oauth_signature_method' => 'RSA-SHA1',
183:             'oauth_consumer_key' => $credentials['consumerKey'],
184:         ];
185:         if (isset($credentials['consumerSecret'])) {
186:             $values['oauth_consumer_secret'] = $credentials['consumerSecret'];
187:         }
188:         if (isset($credentials['token'])) {
189:             $values['oauth_token'] = $credentials['token'];
190:         }
191:         if (isset($credentials['tokenSecret'])) {
192:             $values['oauth_token_secret'] = $credentials['tokenSecret'];
193:         }
194:         $baseString = $this->baseString($request, $values);
195: 
196:         if (isset($credentials['realm'])) {
197:             $values['oauth_realm'] = $credentials['realm'];
198:         }
199: 
200:         if (is_resource($credentials['privateKey'])) {
201:             $resource = $credentials['privateKey'];
202:             $privateKey = stream_get_contents($resource);
203:             rewind($resource);
204:             $credentials['privateKey'] = $privateKey;
205:         }
206: 
207:         $credentials += [
208:             'privateKeyPassphrase' => null,
209:         ];
210:         if (is_resource($credentials['privateKeyPassphrase'])) {
211:             $resource = $credentials['privateKeyPassphrase'];
212:             $passphrase = stream_get_line($resource, 0, PHP_EOL);
213:             rewind($resource);
214:             $credentials['privateKeyPassphrase'] = $passphrase;
215:         }
216:         $privateKey = openssl_pkey_get_private($credentials['privateKey'], $credentials['privateKeyPassphrase']);
217:         $signature = '';
218:         openssl_sign($baseString, $signature, $privateKey);
219:         openssl_free_key($privateKey);
220: 
221:         $values['oauth_signature'] = base64_encode($signature);
222: 
223:         return $this->_buildAuth($values);
224:     }
225: 
226:     /**
227:      * Generate the Oauth basestring
228:      *
229:      * - Querystring, request data and oauth_* parameters are combined.
230:      * - Values are sorted by name and then value.
231:      * - Request values are concatenated and urlencoded.
232:      * - The request URL (without querystring) is normalized.
233:      * - The HTTP method, URL and request parameters are concatenated and returned.
234:      *
235:      * @param \Cake\Http\Client\Request $request The request object.
236:      * @param array $oauthValues Oauth values.
237:      * @return string
238:      */
239:     public function baseString($request, $oauthValues)
240:     {
241:         $parts = [
242:             $request->getMethod(),
243:             $this->_normalizedUrl($request->getUri()),
244:             $this->_normalizedParams($request, $oauthValues),
245:         ];
246:         $parts = array_map([$this, '_encode'], $parts);
247: 
248:         return implode('&', $parts);
249:     }
250: 
251:     /**
252:      * Builds a normalized URL
253:      *
254:      * Section 9.1.2. of the Oauth spec
255:      *
256:      * @param \Psr\Http\Message\UriInterface $uri Uri object to build a normalized version of.
257:      * @return string Normalized URL
258:      */
259:     protected function _normalizedUrl($uri)
260:     {
261:         $out = $uri->getScheme() . '://';
262:         $out .= strtolower($uri->getHost());
263:         $out .= $uri->getPath();
264: 
265:         return $out;
266:     }
267: 
268:     /**
269:      * Sorts and normalizes request data and oauthValues
270:      *
271:      * Section 9.1.1 of Oauth spec.
272:      *
273:      * - URL encode keys + values.
274:      * - Sort keys & values by byte value.
275:      *
276:      * @param \Cake\Http\Client\Request $request The request object.
277:      * @param array $oauthValues Oauth values.
278:      * @return string sorted and normalized values
279:      */
280:     protected function _normalizedParams($request, $oauthValues)
281:     {
282:         $query = parse_url($request->getUri(), PHP_URL_QUERY);
283:         parse_str($query, $queryArgs);
284: 
285:         $post = [];
286:         $body = $request->body();
287:         if (is_string($body) && $request->getHeaderLine('content-type') === 'application/x-www-form-urlencoded') {
288:             parse_str($body, $post);
289:         }
290:         if (is_array($body)) {
291:             $post = $body;
292:         }
293: 
294:         $args = array_merge($queryArgs, $oauthValues, $post);
295:         $pairs = $this->_normalizeData($args);
296:         $data = [];
297:         foreach ($pairs as $pair) {
298:             $data[] = implode('=', $pair);
299:         }
300:         sort($data, SORT_STRING);
301: 
302:         return implode('&', $data);
303:     }
304: 
305:     /**
306:      * Recursively convert request data into the normalized form.
307:      *
308:      * @param array $args The arguments to normalize.
309:      * @param string $path The current path being converted.
310:      * @see https://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
311:      * @return array
312:      */
313:     protected function _normalizeData($args, $path = '')
314:     {
315:         $data = [];
316:         foreach ($args as $key => $value) {
317:             if ($path) {
318:                 // Fold string keys with [].
319:                 // Numeric keys result in a=b&a=c. While this isn't
320:                 // standard behavior in PHP, it is common in other platforms.
321:                 if (!is_numeric($key)) {
322:                     $key = "{$path}[{$key}]";
323:                 } else {
324:                     $key = $path;
325:                 }
326:             }
327:             if (is_array($value)) {
328:                 uksort($value, 'strcmp');
329:                 $data = array_merge($data, $this->_normalizeData($value, $key));
330:             } else {
331:                 $data[] = [$key, $value];
332:             }
333:         }
334: 
335:         return $data;
336:     }
337: 
338:     /**
339:      * Builds the Oauth Authorization header value.
340:      *
341:      * @param array $data The oauth_* values to build
342:      * @return string
343:      */
344:     protected function _buildAuth($data)
345:     {
346:         $out = 'OAuth ';
347:         $params = [];
348:         foreach ($data as $key => $value) {
349:             $params[] = $key . '="' . $this->_encode($value) . '"';
350:         }
351:         $out .= implode(',', $params);
352: 
353:         return $out;
354:     }
355: 
356:     /**
357:      * URL Encodes a value based on rules of rfc3986
358:      *
359:      * @param string $value Value to encode.
360:      * @return string
361:      */
362:     protected function _encode($value)
363:     {
364:         return str_replace(['%7E', '+'], ['~', ' '], rawurlencode($value));
365:     }
366: }
367: 
368: // @deprecated 3.4.0 Add backwards compat alias.
369: class_alias('Cake\Http\Client\Auth\Oauth', 'Cake\Network\Http\Auth\Oauth');
370: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs