Skip to content

Instantly share code, notes, and snippets.

@monkbroc
Created May 28, 2015 17:10
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monkbroc/4251effc7912b9764ca1 to your computer and use it in GitHub Desktop.
Save monkbroc/4251effc7912b9764ca1 to your computer and use it in GitHub Desktop.
Zend 1 Gdata OAuthClient
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Gdata
* @subpackage Gdata
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id: HttpClient.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Http_Client
*/
require_once 'Zend/Http/Client.php';
/**
* Gdata Http Client object.
*
* Class to extend the generic Zend Http Client with the ability to perform
* secure AuthSub requests
*
* @category Zend
* @package Zend_Gdata
* @subpackage Gdata
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Gdata_HttpClient extends Zend_Http_Client
{
/**
* OpenSSL private key resource id
* This key is used for AuthSub authentication. If this value is set,
* it is assuemd that secure AuthSub is desired.
*
* @var resource
*/
private $_authSubPrivateKeyId = null;
/**
* Token for AuthSub authentication.
* If this token is set, AuthSub authentication is used.
*
* @var string
*/
private $_authSubToken = null;
/**
* Token for ClientLogin authentication.
* If only this token is set, ClientLogin authentication is used.
*
* @var string
*/
private $_clientLoginToken = null;
/**
* Token for OAuth
*/
private $_bearerToken = null;
/**
* Token for ClientLogin authentication.
* If this token is set, and the AuthSub key is not set,
* ClientLogin authentication is used
*
* @var string
*/
private $_clientLoginKey = null;
/**
* True if this request is being made with data supplied by
* a stream object instead of a raw encoded string.
*
* @var bool
*/
protected $_streamingRequest = null;
/**
* Sets the PEM formatted private key, as read from a file.
*
* This method reads the file and then calls setAuthSubPrivateKey()
* with the file contents.
*
* @param string $file The location of the file containing the PEM key
* @param string $passphrase The optional private key passphrase
* @param bool $useIncludePath Whether to search the include_path
* for the file
* @return void
*/
public function setAuthSubPrivateKeyFile($file, $passphrase = null,
$useIncludePath = false) {
$fp = @fopen($file, "r", $useIncludePath);
if (!$fp) {
require_once 'Zend/Gdata/App/InvalidArgumentException.php';
throw new Zend_Gdata_App_InvalidArgumentException('Failed to open private key file for AuthSub.');
}
$key = '';
while (!feof($fp)) {
$key .= fread($fp, 8192);
}
$this->setAuthSubPrivateKey($key, $passphrase);
fclose($fp);
}
/**
* Sets the PEM formatted private key to be used for secure AuthSub auth.
*
* In order to call this method, openssl must be enabled in your PHP
* installation. Otherwise, a Zend_Gdata_App_InvalidArgumentException
* will be thrown.
*
* @param string $key The private key
* @param string $passphrase The optional private key passphrase
* @throws Zend_Gdata_App_InvalidArgumentException
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setAuthSubPrivateKey($key, $passphrase = null) {
if ($key != null && !function_exists('openssl_pkey_get_private')) {
require_once 'Zend/Gdata/App/InvalidArgumentException.php';
throw new Zend_Gdata_App_InvalidArgumentException(
'You cannot enable secure AuthSub if the openssl module ' .
'is not enabled in your PHP installation.');
}
$this->_authSubPrivateKeyId = openssl_pkey_get_private(
$key, $passphrase);
return $this;
}
/**
* Gets the openssl private key id
*
* @return string The private key
*/
public function getAuthSubPrivateKeyId() {
return $this->_authSubPrivateKeyId;
}
/**
* Gets the AuthSub token used for authentication
*
* @return string The token
*/
public function getAuthSubToken() {
return $this->_authSubToken;
}
/**
* Sets the AuthSub token used for authentication
*
* @param string $token The token
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setAuthSubToken($token) {
$this->_authSubToken = $token;
return $this;
}
/**
* Gets the ClientLogin token used for authentication
*
* @return string The token
*/
public function getClientLoginToken() {
return $this->_clientLoginToken;
}
/**
* Sets the ClientLogin token used for authentication
*
* @param string $token The token
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setClientLoginToken($token) {
$this->_clientLoginToken = $token;
return $this;
}
/**
* Gets the Bearer token used for authentication
*
* @return string The token
*/
public function getBearerToken() {
return $this->_bearerToken;
}
/**
* Sets the Bearer token used for authentication
*
* @param string $token The token
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setBearerToken($token) {
$this->_bearerToken = $token;
return $this;
}
/**
* Filters the HTTP requests being sent to add the Authorization header.
*
* If both AuthSub and ClientLogin tokens are set,
* AuthSub takes precedence. If an AuthSub key is set, then
* secure AuthSub authentication is used, and the request is signed.
* Requests must be signed only with the private key corresponding to the
* public key registered with Google. If an AuthSub key is set, but
* openssl support is not enabled in the PHP installation, an exception is
* thrown.
*
* @param string $method The HTTP method
* @param string $url The URL
* @param array $headers An associate array of headers to be
* sent with the request or null
* @param string $body The body of the request or null
* @param string $contentType The MIME content type of the body or null
* @throws Zend_Gdata_App_Exception if there was a signing failure
* @return array The processed values in an associative array,
* using the same names as the params
*/
public function filterHttpRequest($method, $url, $headers = array(), $body = null, $contentType = null) {
if ($this->getAuthSubToken() != null) {
// AuthSub authentication
if ($this->getAuthSubPrivateKeyId() != null) {
// secure AuthSub
$time = time();
$nonce = mt_rand(0, 999999999);
$dataToSign = $method . ' ' . $url . ' ' . $time . ' ' . $nonce;
// compute signature
$pKeyId = $this->getAuthSubPrivateKeyId();
$signSuccess = openssl_sign($dataToSign, $signature, $pKeyId,
OPENSSL_ALGO_SHA1);
if (!$signSuccess) {
require_once 'Zend/Gdata/App/Exception.php';
throw new Zend_Gdata_App_Exception(
'openssl_signing failure - returned false');
}
// encode signature
$encodedSignature = base64_encode($signature);
// final header
$headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '" ' .
'data="' . $dataToSign . '" ' .
'sig="' . $encodedSignature . '" ' .
'sigalg="rsa-sha1"';
} else {
// AuthSub without secure tokens
$headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '"';
}
} elseif ($this->getClientLoginToken() != null) {
$headers['authorization'] = 'GoogleLogin auth=' . $this->getClientLoginToken();
} elseif ($this->getBearerToken() != null) {
$headers['authorization'] = 'Bearer ' . $this->getBearerToken();
}
return array('method' => $method, 'url' => $url, 'body' => $body, 'headers' => $headers, 'contentType' => $contentType);
}
/**
* Method for filtering the HTTP response, though no filtering is
* currently done.
*
* @param Zend_Http_Response $response The response object to filter
* @return Zend_Http_Response The filterd response object
*/
public function filterHttpResponse($response) {
return $response;
}
/**
* Return the current connection adapter
*
* @return Zend_Http_Client_Adapter_Interface|string $adapter
*/
public function getAdapter()
{
return $this->adapter;
}
/**
* Load the connection adapter
*
* @param Zend_Http_Client_Adapter_Interface $adapter
* @return void
*/
public function setAdapter($adapter)
{
if ($adapter == null) {
$this->adapter = $adapter;
} else {
parent::setAdapter($adapter);
}
}
/**
* Set the streamingRequest variable which controls whether we are
* sending the raw (already encoded) POST data from a stream source.
*
* @param boolean $value The value to set.
* @return void
*/
public function setStreamingRequest($value)
{
$this->_streamingRequest = $value;
}
/**
* Check whether the client is set to perform streaming requests.
*
* @return boolean True if yes, false otherwise.
*/
public function getStreamingRequest()
{
if ($this->_streamingRequest()) {
return true;
} else {
return false;
}
}
/**
* Prepare the request body (for POST and PUT requests)
*
* @return string
* @throws Zend_Http_Client_Exception
*/
protected function _prepareBody()
{
if($this->_streamingRequest) {
$this->setHeaders(self::CONTENT_LENGTH,
$this->raw_post_data->getTotalSize());
return $this->raw_post_data;
}
else {
return parent::_prepareBody();
}
}
/**
* Clear all custom parameters we set.
*
* @return Zend_Http_Client
*/
public function resetParameters($clearAll = false)
{
$this->_streamingRequest = false;
return parent::resetParameters($clearAll);
}
/**
* Set the raw (already encoded) POST data from a stream source.
*
* This is used to support POSTing from open file handles without
* caching the entire body into memory. It is a wrapper around
* Zend_Http_Client::setRawData().
*
* @param string $data The request data
* @param string $enctype The encoding type
* @return Zend_Http_Client
*/
public function setRawDataStream($data, $enctype = null)
{
$this->_streamingRequest = true;
return $this->setRawData($data, $enctype);
}
}
<?php
/**
* Zend_Gdata_HttpClient
*/
require_once 'Zend/Gdata/HttpClient.php';
/**
* Zend_Version
*/
require_once 'Zend/Version.php';
/**
* Class to facilitate Google's "Account Authentication
* for Installed Applications" also known as "ClientLogin".
* @see http://code.google.com/apis/accounts/AuthForInstalledApps.html
*
* @category Zend
* @package Zend_Gdata
* @subpackage Gdata
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Gdata_OAuthClient
{
const TOKEN_CREDENTIAL_URI = 'https://www.googleapis.com/oauth2/v3/token';
/**
* The default 'source' parameter to send to Google
*
*/
const DEFAULT_SOURCE = 'Zend-ZendFramework';
/**
* Set Google authentication credentials.
* Must be done before trying to do any Google Data operations that
* require authentication.
* For example, viewing private data, or posting or deleting entries.
*
* @param string $email
* @param string $password
* @param string $service
* @param Zend_Gdata_HttpClient $client
* @param string $source
* @param string $loginToken The token identifier as provided by the server.
* @param string $loginCaptcha The user's response to the CAPTCHA challenge.
* @param string $accountType An optional string to identify whether the
* account to be authenticated is a google or a hosted account. Defaults to
* 'HOSTED_OR_GOOGLE'. See: http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request
* @throws Zend_Gdata_App_AuthException
* @throws Zend_Gdata_App_HttpException
* @throws Zend_Gdata_App_CaptchaRequiredException
* @return Zend_Gdata_HttpClient
*/
public static function getHttpClient($clientId, $clientSecret, $refreshToken,
$client = null,
$source = self::DEFAULT_SOURCE,
$tokenCredentialUri = self::TOKEN_CREDENTIAL_URI)
{
if (! ($clientId && $clientSecret && $refreshToken)) {
require_once 'Zend/Gdata/App/AuthException.php';
throw new Zend_Gdata_App_AuthException(
'Missing Google credentials before trying to ' .
'authenticate');
}
if ($client == null) {
$client = new Zend_Gdata_HttpClient();
}
if (!$client instanceof Zend_Http_Client) {
require_once 'Zend/Gdata/App/HttpException.php';
throw new Zend_Gdata_App_HttpException(
'Client is not an instance of Zend_Http_Client.');
}
// Build the HTTP client for authentication
$client->setUri($tokenCredentialUri);
$useragent = $source . ' Zend_Framework_Gdata/' . Zend_Version::VERSION;
$client->setConfig(array(
'maxredirects' => 0,
'strictredirects' => true,
'useragent' => $useragent
)
);
$client->setParameterPost('grant_type', 'refresh_token');
$client->setParameterPost('refresh_token', (string) $refreshToken);
$client->setParameterPost('client_id', (string) $clientId);
$client->setParameterPost('client_secret', (string) $clientSecret);
// Send the authentication request
// For some reason Google's server causes an SSL error. We use the
// output buffer to supress an error from being shown. Ugly - but works!
ob_start();
try {
$response = $client->request('POST');
} catch (Zend_Http_Client_Exception $e) {
require_once 'Zend/Gdata/App/HttpException.php';
throw new Zend_Gdata_App_HttpException($e->getMessage(), $e);
}
ob_end_clean();
// Parse Google's response
$goog_resp = json_decode($response->getBody());
if ($response->getStatus() == 200) {
$client->setBearerToken($goog_resp->{'access_token'});
$useragent = $source . ' Zend_Framework_Gdata/' . Zend_Version::VERSION;
$client->setConfig(array(
'strictredirects' => true,
'useragent' => $useragent
)
);
return $client;
} else {
require_once 'Zend/Gdata/App/AuthException.php';
throw new Zend_Gdata_App_AuthException('Authentication with Google failed. Reason: ' .
$goog_resp->{'error_description'});
}
}
}
Copy link

ghost commented Oct 25, 2015

Excellent! Thank you! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment