* Copyright 2010 Google Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
if (!class_exists('UDP_Google_Client')) {
require_once dirname(__FILE__) . '/../autoload.php';
* http://code.google.com/p/google-api-php-client/
const USER_AGENT_SUFFIX = "google-api-php-client-ud/";
* @var Google_Auth_Abstract $auth
* @var UDP_Google_IO_Abstract $io
* @var Google_Cache_Abstract $cache
* @var UDP_Google_Config $config
* @var Google_Logger_Abstract $logger
* @var boolean $deferExecution
private $deferExecution = false;
/** @var array $scopes */
// Scopes requested by the client
protected $requestedScopes = array();
// definitions of services that are discovered.
protected $services = array();
// Used to track authenticated state, can't discover services after doing authenticate()
private $authenticated = false;
* Construct the Google Client.
* @param $config UDP_Google_Config or string for the ini file to load
public function __construct($config = null)
if (is_string($config) && strlen($config)) {
$config = new UDP_Google_Config($config);
} else if ( !($config instanceof UDP_Google_Config)) {
$config = new UDP_Google_Config();
if ($this->isAppEngine()) {
// Automatically use Memcache if we're in AppEngine.
$config->setCacheClass('Google_Cache_Memcache');
if (version_compare(phpversion(), "5.3.4", "<=") || $this->isAppEngine()) {
// Automatically disable compress.zlib, as currently unsupported.
$config->setClassConfig('UDP_Google_Http_Request', 'disable_gzip', true);
if ($config->getIoClass() == UDP_Google_Config::USE_AUTO_IO_SELECTION) {
if (function_exists('curl_version') && function_exists('curl_exec')
&& !$this->isAppEngine()) {
$config->setIoClass("UDP_Google_IO_Curl");
$config->setIoClass("UDP_Google_IO_Stream");
* Get a string containing the version of the library.
public function getLibraryVersion()
* Attempt to exchange a code for an valid authentication token.
* Helper wrapped around the OAuth 2.0 implementation.
* @param $code string code from accounts.google.com
public function authenticate($code)
$this->authenticated = true;
return $this->getAuth()->authenticate($code);
* Loads a service account key and parameters from a JSON
* file from the Google Developer Console. Uses that and the
* given array of scopes to return an assertion credential for
* use with refreshTokenWithAssertionCredential.
* @param string $jsonLocation File location of the project-key.json.
* @param array $scopes The scopes to assert.
* @return Google_Auth_AssertionCredentials.
public function loadServiceAccountJson($jsonLocation, $scopes)
$data = json_decode(file_get_contents($jsonLocation));
if (isset($data->type) && $data->type == 'service_account') {
// Service Account format.
$cred = new Google_Auth_AssertionCredentials(
throw new Google_Exception("Invalid service account JSON file.");
* Set the auth config from the JSON string provided.
* This structure should match the file downloaded from
* the "Download JSON" button on in the Google Developer
* @param string $json the configuration json
* @throws Google_Exception
public function setAuthConfig($json)
$data = json_decode($json);
$key = isset($data->installed) ? 'installed' : 'web';
if (!isset($data->$key)) {
throw new Google_Exception("Invalid client secret JSON file.");
$this->setClientId($data->$key->client_id);
$this->setClientSecret($data->$key->client_secret);
if (isset($data->$key->redirect_uris)) {
$this->setRedirectUri($data->$key->redirect_uris[0]);
* Set the auth config from the JSON file in the path
* provided. This should match the file downloaded from
* the "Download JSON" button on in the Google Developer
* @param string $file the file location of the client json
public function setAuthConfigFile($file)
$this->setAuthConfig(file_get_contents($file));
* @throws Google_Auth_Exception
public function prepareScopes()
if (empty($this->requestedScopes)) {
throw new Google_Auth_Exception("No scopes specified");
$scopes = implode(' ', $this->requestedScopes);
* Set the OAuth 2.0 access token using the string that resulted from calling createAuthUrl()
* or UDP_Google_Client#getAccessToken().
* @param string $accessToken JSON encoded string containing in the following format:
* {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer",
* "expires_in":3600, "id_token":"TOKEN", "created":1320790426}
public function setAccessToken($accessToken)
if ($accessToken == 'null') {
$this->getAuth()->setAccessToken($accessToken);
* Set the authenticator object
* @param Google_Auth_Abstract $auth
public function setAuth(Google_Auth_Abstract $auth)
$this->config->setAuthClass(get_class($auth));
* @param UDP_Google_IO_Abstract $io
public function setIo(UDP_Google_IO_Abstract $io)
$this->config->setIoClass(get_class($io));
* @param Google_Cache_Abstract $cache
public function setCache(Google_Cache_Abstract $cache)
$this->config->setCacheClass(get_class($cache));
* @param Google_Logger_Abstract $logger
public function setLogger(Google_Logger_Abstract $logger)
$this->config->setLoggerClass(get_class($logger));
* Construct the OAuth 2.0 authorization request URI.
public function createAuthUrl()
$scopes = $this->prepareScopes();
return $this->getAuth()->createAuthUrl($scopes);
* Get the OAuth 2.0 access token.
* @return string $accessToken JSON encoded string in the following format:
* {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer",
* "expires_in":3600,"id_token":"TOKEN", "created":1320790426}
public function getAccessToken()
$token = $this->getAuth()->getAccessToken();
// The response is json encoded, so could be the string null.
// It is arguable whether this check should be here or lower
return (null == $token || 'null' == $token || '[]' == $token) ? null : $token;
* Get the OAuth 2.0 refresh token.
* @return string $refreshToken refresh token or null if not available
public function getRefreshToken()
return $this->getAuth()->getRefreshToken();
* Returns if the access_token is expired.
* @return bool Returns True if the access_token is expired.
public function isAccessTokenExpired()
return $this->getAuth()->isAccessTokenExpired();
* Set OAuth 2.0 "state" parameter to achieve per-request customization.
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2
public function setState($state)
$this->getAuth()->setState($state);
* @param string $accessType Possible values for access_type include:
* {@code "offline"} to request offline access from the user.
* {@code "online"} to request online access from the user.
public function setAccessType($accessType)
$this->config->setAccessType($accessType);
* @param string $approvalPrompt Possible values for approval_prompt include:
* {@code "force"} to force the approval UI to appear. (This is the default value)
* {@code "auto"} to request auto-approval when possible.
public function setApprovalPrompt($approvalPrompt)
$this->config->setApprovalPrompt($approvalPrompt);
* Set the login hint, email address or sub id.
* @param string $loginHint
public function setLoginHint($loginHint)
$this->config->setLoginHint($loginHint);
* Set the application name, this is included in the User-Agent HTTP header.
* @param string $applicationName
public function setApplicationName($applicationName)
$this->config->setApplicationName($applicationName);
* Set the OAuth 2.0 Client ID.
* @param string $clientId
public function setClientId($clientId)
$this->config->setClientId($clientId);
* Set the OAuth 2.0 Client Secret.
* @param string $clientSecret
public function setClientSecret($clientSecret)
$this->config->setClientSecret($clientSecret);
* Set the OAuth 2.0 Redirect URI.
* @param string $redirectUri
public function setRedirectUri($redirectUri)
$this->config->setRedirectUri($redirectUri);
* If 'plus.login' is included in the list of requested scopes, you can use
* this method to define types of app activities that your app will write.
* You can find a list of available types here:
* @link https://developers.google.com/+/api/moment-types
* @param array $requestVisibleActions Array of app activity types
public function setRequestVisibleActions($requestVisibleActions)
if (is_array($requestVisibleActions)) {
$requestVisibleActions = join(" ", $requestVisibleActions);
$this->config->setRequestVisibleActions($requestVisibleActions);
* Set the developer key to use, these are obtained through the API Console.
* @see http://code.google.com/apis/console-help/#generatingdevkeys
* @param string $developerKey
public function setDeveloperKey($developerKey)
$this->config->setDeveloperKey($developerKey);
* Set the hd (hosted domain) parameter streamlines the login process for
* Google Apps hosted accounts. By including the domain of the user, you
* restrict sign-in to accounts at that domain.
* @param $hd string - the domain to use.
public function setHostedDomain($hd)
$this->config->setHostedDomain($hd);
* Set the prompt hint. Valid values are none, consent and select_account.
* If no value is specified and the user has not previously authorized
* access, then the user is shown a consent screen.
public function setPrompt($prompt)
$this->config->setPrompt($prompt);
* openid.realm is a parameter from the OpenID 2.0 protocol, not from OAuth
* 2.0. It is used in OpenID 2.0 requests to signify the URL-space for which
* an authentication request is valid.
* @param $realm string - the URL-space to use.
public function setOpenidRealm($realm)
$this->config->setOpenidRealm($realm);
* If this is provided with the value true, and the authorization request is
* granted, the authorization will include any previous authorizations
* granted to this user/application combination for other scopes.
* @param $include boolean - the URL-space to use.
public function setIncludeGrantedScopes($include)
$this->config->setIncludeGrantedScopes($include);
* Fetches a fresh OAuth 2.0 access token with the given refresh token.
* @param string $refreshToken
public function refreshToken($refreshToken)
$this->getAuth()->refreshToken($refreshToken);
* Revoke an OAuth2 access token or refresh token. This method will revoke the current access
* token, if a token isn't provided.
* @throws Google_Auth_Exception
* @param string|null $token The token (access token or a refresh token) that should be revoked.
* @return boolean Returns True if the revocation was successful, otherwise False.
public function revokeToken($token = null)
return $this->getAuth()->revokeToken($token);
* Verify an id_token. This method will verify the current id_token, if one
* @throws Google_Auth_Exception
* @param string|null $token The token (id_token) that should be verified.
* @return Google_Auth_LoginTicket Returns an apiLoginTicket if the verification was
public function verifyIdToken($token = null)
return $this->getAuth()->verifyIdToken($token);
* Verify a JWT that was signed with your own certificates.
* @param $id_token string The JWT token
* @param $cert_location array of certificates
* @param $audience string the expected consumer of the token
* @param $issuer string the expected issuer, defaults to Google
* @param [$max_expiry] the max lifetime of a token, defaults to MAX_TOKEN_LIFETIME_SECS
* @return mixed token information if valid, false if not
public function verifySignedJwt($id_token, $cert_location, $audience, $issuer, $max_expiry = null)
$auth = new Google_Auth_OAuth2($this);
$certs = $auth->retrieveCertsFromLocation($cert_location);
return $auth->verifySignedJwtWithCerts($id_token, $certs, $audience, $issuer, $max_expiry);
* @param $creds Google_Auth_AssertionCredentials