Skip to content

Commit

Permalink
adds PSR-6 and removes custom caching (#943)
Browse files Browse the repository at this point in the history
* adds PSR-6 and removes custom caching

* Adds callback

* documents these changes in the README
  • Loading branch information
bshaffer committed May 13, 2016
1 parent b8c815b commit f872fea
Show file tree
Hide file tree
Showing 20 changed files with 190 additions and 943 deletions.
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ $ php -S localhost:8000 -t examples/
And then browsing to the host and port you specified
(in the above example, `http://localhost:8000`).

```PHP
```php
// include your composer dependencies
require_once 'vendor/autoload.php';

Expand All @@ -79,6 +79,33 @@ foreach ($results as $item) {
}
```

### Caching ###

It is recommended to use another caching library to improve performance. This can be done by passing a [PSR-6](http://www.php-fig.org/psr/psr-6/) compatible library to the client:

```php
$cache = new Stash\Pool(new Stash\Driver\FileSystem);
$client->setCache($cache);
```

In this example we use [StashPHP](http://www.stashphp.com/). Add this to your project with composer:

```
composer require tedivm/stash
```

### Updating Tokens ###

When using [Refresh Tokens](https://developers.google.com/identity/protocols/OAuth2InstalledApp#refresh) or [Service Account Credentials](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#overview), it may be useful to perform some action when a new access token is granted. To do this, pass a callable to the `setTokenCallback` method on the client:

```php
$logger = new Monolog\Logger;
$tokenCallback = function ($cacheKey, $accessToken) use ($logger) {
$logger->debug(sprintf('new access token received at cache key %s', $cacheKey));
};
$client->setTokenCallback($tokenCallback);
```

### Service Specific Examples ###

YouTube: https://github.com/youtube/api-samples/tree/master/php
Expand All @@ -87,9 +114,9 @@ YouTube: https://github.com/youtube/api-samples/tree/master/php

### What do I do if something isn't working? ###

For support with the library the best place to ask is via the google-api-php-client tag on StackOverflow: http://stackoverflow.com/questions/tagged/google-api-php-client
For support with the library the best place to ask is via the google-api-php-client tag on StackOverflow: http://stackoverflow.com/questions/tagged/google-api-php-client

If there is a specific bug with the library, please file a issue in the Github issues tracker, including a (minimal) example of the failing code and any specific errors retrieved. Feature requests can also be filed, as long as they are core library requests, and not-API specific: for those, refer to the documentation for the individual APIs for the best place to file requests. Please try to provide a clear statement of the problem that the feature would address.
If there is a specific bug with the library, please [file a issue](/Google/google-api-php-client/issues) in the Github issues tracker, including an example of the failing code and any specific errors retrieved. Feature requests can also be filed, as long as they are core library requests, and not-API specific: for those, refer to the documentation for the individual APIs for the best place to file requests. Please try to provide a clear statement of the problem that the feature would address.

### How do I contribute? ###

Expand Down
13 changes: 8 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,23 @@
"license": "Apache-2.0",
"require": {
"php": ">=5.4",
"google/auth": "0.7",
"google/auth": "0.8",
"google/apiclient-services": "*@dev",
"firebase/php-jwt": "~2.0|~3.0",
"monolog/monolog": "^1.17",
"phpseclib/phpseclib": "~2.0",
"guzzlehttp/guzzle": "~5.2|~6.0",
"guzzlehttp/psr7": "1.2.*",
"psr/http-message": "1.0.*"
"guzzlehttp/psr7": "^1.2"
},
"require-dev": {
"phpunit/phpunit": "~4",
"squizlabs/php_codesniffer": "~2.3",
"symfony/dom-crawler": "~2.0",
"symfony/css-selector": "~2.0"
"symfony/dom-crawler": "~2.1",
"symfony/css-selector": "~2.1",
"tedivm/stash": "^0.14.1"
},
"suggest": {
"tedivm/stash": "For caching certs and tokens (using Google_Client::setCache)"
},
"autoload": {
"psr-0": {
Expand Down
45 changes: 25 additions & 20 deletions src/Google/AccessToken/Verify.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
*/

use Firebase\JWT\ExpiredException as ExpiredExceptionV3;
use Google\Auth\CacheInterface;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use phpseclib\Crypt\RSA;
use phpseclib\Math\BigInteger;
use Psr\Cache\CacheItemPoolInterface;
use Stash\Driver\FileSystem;
use Stash\Pool;

/**
* Wrapper around Google Access Tokens which provides convenience functions
Expand All @@ -39,20 +41,24 @@ class Google_AccessToken_Verify
private $http;

/**
* @var Google\Auth\CacheInterface cache class
* @var Psr\Cache\CacheItemPoolInterface cache class
*/
private $cache;

/**
* Instantiates the class, but does not initiate the login flow, leaving it
* to the discretion of the caller.
*/
public function __construct(ClientInterface $http = null, CacheInterface $cache = null)
public function __construct(ClientInterface $http = null, CacheItemPoolInterface $cache = null)
{
if (is_null($http)) {
$http = new Client();
}

if (is_null($cache) && class_exists('Stash\Pool')) {
$cache = new Pool(new FileSystem);
}

$this->http = $http;
$this->cache = $cache;
$this->jwt = $this->getJwtService();
Expand Down Expand Up @@ -120,20 +126,9 @@ public function verifyIdToken($idToken, $audience = null)

private function getCache()
{
if (!$this->cache) {
$this->cache = $this->createDefaultCache();
}

return $this->cache;
}

private function createDefaultCache()
{
return new Google_Cache_File(
sys_get_temp_dir().'/google-api-php-client'
);
}

/**
* Retrieve and cache a certificates file.
*
Expand Down Expand Up @@ -174,14 +169,22 @@ private function retrieveCertsFromLocation($url)
// are PEM encoded certificates.
private function getFederatedSignOnCerts()
{
$cache = $this->getCache();
$certs = null;
if ($cache = $this->getCache()) {
$cacheItem = $cache->getItem('federated_signon_certs_v3', 3600);
$certs = $cacheItem->get();
}

if (!$certs = $cache->get('federated_signon_certs_v3', 3600)) {

if (!$certs) {
$certs = $this->retrieveCertsFromLocation(
self::FEDERATED_SIGNON_CERT_URL
);

$cache->set('federated_signon_certs_v3', $certs);
if ($cache) {
$cacheItem->set($certs);
$cache->save($cacheItem);
}
}

if (!isset($certs['keys'])) {
Expand All @@ -200,9 +203,11 @@ private function getJwtService()
$jwtClass = 'Firebase\JWT\JWT';
}

// adds 1 second to JWT leeway
// @see https://github.com/google/google-api-php-client/issues/827
$jwtClass::$leeway = 1;
if (property_exists($jwtClass, 'leeway')) {
// adds 1 second to JWT leeway
// @see https://github.com/google/google-api-php-client/issues/827
$jwtClass::$leeway = 1;
}

return new $jwtClass;
}
Expand Down
6 changes: 3 additions & 3 deletions src/Google/AuthHandler/AuthHandlerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ class Google_AuthHandler_AuthHandlerFactory
* @return Google_AuthHandler_Guzzle5AuthHandler|Google_AuthHandler_Guzzle6AuthHandler
* @throws Exception
*/
public static function build($cache = null)
public static function build($cache = null, array $cacheConfig = [])
{
$version = ClientInterface::VERSION;

switch ($version[0]) {
case '5':
return new Google_AuthHandler_Guzzle5AuthHandler($cache);
return new Google_AuthHandler_Guzzle5AuthHandler($cache, $cacheConfig);
case '6':
return new Google_AuthHandler_Guzzle6AuthHandler($cache);
return new Google_AuthHandler_Guzzle6AuthHandler($cache, $cacheConfig);
default:
throw new Exception('Version not supported');
}
Expand Down
18 changes: 12 additions & 6 deletions src/Google/AuthHandler/Guzzle5AuthHandler.php
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
<?php

use Google\Auth\CacheInterface;
use Google\Auth\CredentialsLoader;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use Google\Auth\Subscriber\AuthTokenSubscriber;
use Google\Auth\Subscriber\ScopedAccessTokenSubscriber;
use Google\Auth\Subscriber\SimpleSubscriber;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use Psr\Cache\CacheItemPoolInterface;

/**
*
*/
class Google_AuthHandler_Guzzle5AuthHandler
{
protected $cache;
protected $cacheConfig;

public function __construct(CacheInterface $cache = null)
public function __construct(CacheItemPoolInterface $cache = null, array $cacheConfig = [])
{
$this->cache = $cache;
$this->cacheConfig = $cacheConfig;
}

public function attachCredentials(ClientInterface $http, CredentialsLoader $credentials)
{
public function attachCredentials(
ClientInterface $http,
CredentialsLoader $credentials,
callable $tokenCallback = null
) {
// if we end up needing to make an HTTP request to retrieve credentials, we
// can use our existing one, but we need to throw exceptions so the error
// bubbles up.
$authHttp = $this->createAuthHttp($http);
$authHttpHandler = HttpHandlerFactory::build($authHttp);
$subscriber = new AuthTokenSubscriber(
$credentials,
[],
$this->cacheConfig,
$this->cache,
$authHttpHandler
$authHttpHandler,
$tokenCallback
);

$http->setDefaultOption('auth', 'google_auth');
Expand Down
18 changes: 12 additions & 6 deletions src/Google/AuthHandler/Guzzle6AuthHandler.php
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
<?php

use Google\Auth\CacheInterface;
use Google\Auth\CredentialsLoader;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use Google\Auth\Middleware\AuthTokenMiddleware;
use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
use Google\Auth\Middleware\SimpleMiddleware;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use Psr\Cache\CacheItemPoolInterface;

/**
*
*/
class Google_AuthHandler_Guzzle6AuthHandler
{
protected $cache;
protected $cacheConfig;

public function __construct(CacheInterface $cache = null)
public function __construct(CacheItemPoolInterface $cache = null, array $cacheConfig = [])
{
$this->cache = $cache;
$this->cacheConfig = $cacheConfig;
}

public function attachCredentials(ClientInterface $http, CredentialsLoader $credentials)
{
public function attachCredentials(
ClientInterface $http,
CredentialsLoader $credentials,
callable $tokenCallback = null
) {
// if we end up needing to make an HTTP request to retrieve credentials, we
// can use our existing one, but we need to throw exceptions so the error
// bubbles up.
$authHttp = $this->createAuthHttp($http);
$authHttpHandler = HttpHandlerFactory::build($authHttp);
$middleware = new AuthTokenMiddleware(
$credentials,
[],
$this->cacheConfig,
$this->cache,
$authHttpHandler
$authHttpHandler,
$tokenCallback
);

$config = $http->getConfig();
Expand Down
Loading

0 comments on commit f872fea

Please sign in to comment.