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.7 Red Velvet API

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