vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php line 151

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright 2015 Google Inc.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. namespace Google\Auth\Middleware;
  18. use Google\Auth\CacheTrait;
  19. use Psr\Cache\CacheItemPoolInterface;
  20. use Psr\Http\Message\RequestInterface;
  21. /**
  22.  * ScopedAccessTokenMiddleware is a Guzzle Middleware that adds an Authorization
  23.  * header provided by a closure.
  24.  *
  25.  * The closure returns an access token, taking the scope, either a single
  26.  * string or an array of strings, as its value.  If provided, a cache will be
  27.  * used to preserve the access token for a given lifetime.
  28.  *
  29.  * Requests will be accessed with the authorization header:
  30.  *
  31.  * 'authorization' 'Bearer <value of auth_token>'
  32.  */
  33. class ScopedAccessTokenMiddleware
  34. {
  35.     use CacheTrait;
  36.     const DEFAULT_CACHE_LIFETIME 1500;
  37.     /**
  38.      * @var callable
  39.      */
  40.     private $tokenFunc;
  41.     /**
  42.      * @var array<string>|string
  43.      */
  44.     private $scopes;
  45.     /**
  46.      * Creates a new ScopedAccessTokenMiddleware.
  47.      *
  48.      * @param callable $tokenFunc a token generator function
  49.      * @param array<string>|string $scopes the token authentication scopes
  50.      * @param array<mixed> $cacheConfig configuration for the cache when it's present
  51.      * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface
  52.      */
  53.     public function __construct(
  54.         callable $tokenFunc,
  55.         $scopes,
  56.         ?array $cacheConfig null,
  57.         ?CacheItemPoolInterface $cache null
  58.     ) {
  59.         $this->tokenFunc $tokenFunc;
  60.         if (!(is_string($scopes) || is_array($scopes))) {
  61.             throw new \InvalidArgumentException(
  62.                 'wants scope should be string or array'
  63.             );
  64.         }
  65.         $this->scopes $scopes;
  66.         if (!is_null($cache)) {
  67.             $this->cache $cache;
  68.             $this->cacheConfig array_merge([
  69.                 'lifetime' => self::DEFAULT_CACHE_LIFETIME,
  70.                 'prefix' => '',
  71.             ], $cacheConfig);
  72.         }
  73.     }
  74.     /**
  75.      * Updates the request with an Authorization header when auth is 'scoped'.
  76.      *
  77.      *   E.g this could be used to authenticate using the AppEngine
  78.      *   AppIdentityService.
  79.      *
  80.      *   use google\appengine\api\app_identity\AppIdentityService;
  81.      *   use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
  82.      *   use GuzzleHttp\Client;
  83.      *   use GuzzleHttp\HandlerStack;
  84.      *
  85.      *   $scope = 'https://www.googleapis.com/auth/taskqueue'
  86.      *   $middleware = new ScopedAccessTokenMiddleware(
  87.      *       'AppIdentityService::getAccessToken',
  88.      *       $scope,
  89.      *       [ 'prefix' => 'Google\Auth\ScopedAccessToken::' ],
  90.      *       $cache = new Memcache()
  91.      *   );
  92.      *   $stack = HandlerStack::create();
  93.      *   $stack->push($middleware);
  94.      *
  95.      *   $client = new Client([
  96.      *       'handler' => $stack,
  97.      *       'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
  98.      *       'auth' => 'scoped' // authorize all requests
  99.      *   ]);
  100.      *
  101.      *   $res = $client->get('myproject/taskqueues/myqueue');
  102.      *
  103.      * @param callable $handler
  104.      * @return \Closure
  105.      */
  106.     public function __invoke(callable $handler)
  107.     {
  108.         return function (RequestInterface $request, array $options) use ($handler) {
  109.             // Requests using "auth"="scoped" will be authorized.
  110.             if (!isset($options['auth']) || $options['auth'] !== 'scoped') {
  111.                 return $handler($request$options);
  112.             }
  113.             $request $request->withHeader('authorization''Bearer ' $this->fetchToken());
  114.             return $handler($request$options);
  115.         };
  116.     }
  117.     /**
  118.      * @return string
  119.      */
  120.     private function getCacheKey()
  121.     {
  122.         $key null;
  123.         if (is_string($this->scopes)) {
  124.             $key .= $this->scopes;
  125.         } elseif (is_array($this->scopes)) {
  126.             $key .= implode(':'$this->scopes);
  127.         }
  128.         return $key;
  129.     }
  130.     /**
  131.      * Determine if token is available in the cache, if not call tokenFunc to
  132.      * fetch it.
  133.      *
  134.      * @return string
  135.      */
  136.     private function fetchToken()
  137.     {
  138.         $cacheKey $this->getCacheKey();
  139.         $cached $this->getCachedValue($cacheKey);
  140.         if (!empty($cached)) {
  141.             return $cached;
  142.         }
  143.         $token call_user_func($this->tokenFunc$this->scopes);
  144.         $this->setCachedValue($cacheKey$token);
  145.         return $token;
  146.     }
  147. }