File: /var/www/agighana.org_backup/OAuth_Client_Base.php
<?php
/**
* Class Google\Site_Kit\Core\Authentication\Clients\OAuth_Client_Base
*
* @package Google\Site_Kit
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Core\Authentication\Clients;
use Exception;
use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Authentication\Credentials;
use Google\Site_Kit\Core\Authentication\Exception\Google_Proxy_Code_Exception;
use Google\Site_Kit\Core\Authentication\Google_Proxy;
use Google\Site_Kit\Core\Authentication\Profile;
use Google\Site_Kit\Core\Authentication\Token;
use Google\Site_Kit\Core\Permissions\Permissions;
use Google\Site_Kit\Core\Storage\Encrypted_Options;
use Google\Site_Kit\Core\Storage\Options;
use Google\Site_Kit\Core\Storage\User_Options;
/**
* Base class for connecting to Google APIs via OAuth.
*
* @since 1.39.0
* @access private
* @ignore
*/
abstract class OAuth_Client_Base {
const OPTION_ACCESS_TOKEN = 'googlesitekit_access_token';
const OPTION_ACCESS_TOKEN_EXPIRES_IN = 'googlesitekit_access_token_expires_in';
const OPTION_ACCESS_TOKEN_CREATED = 'googlesitekit_access_token_created_at';
const OPTION_REFRESH_TOKEN = 'googlesitekit_refresh_token';
const OPTION_AUTH_SCOPES = 'googlesitekit_auth_scopes';
const OPTION_ERROR_CODE = 'googlesitekit_error_code';
const OPTION_PROXY_ACCESS_CODE = 'googlesitekit_proxy_access_code';
/**
* Plugin context.
*
* @since 1.39.0
* @var Context
*/
protected $context;
/**
* Options instance
*
* @since 1.39.0
* @var Options
*/
protected $options;
/**
* User_Options instance
*
* @since 1.39.0
* @var User_Options
*/
protected $user_options;
/**
* OAuth credentials instance.
*
* @since 1.39.0
* @var Credentials
*/
protected $credentials;
/**
* Google_Proxy instance.
*
* @since 1.39.0
* @var Google_Proxy
*/
protected $google_proxy;
/**
* Google Client object.
*
* @since 1.39.0
* @var Google_Site_Kit_Client
*/
protected $google_client;
/**
* Profile instance.
*
* @since 1.39.0
* @var Profile
*/
protected $profile;
/**
* Token instance.
*
* @since 1.39.0
* @var Token
*/
protected $token;
/**
* Constructor.
*
* @since 1.39.0
*
* @param Context $context Plugin context.
* @param Options $options Optional. Option API instance. Default is a new instance.
* @param User_Options $user_options Optional. User Option API instance. Default is a new instance.
* @param Credentials $credentials Optional. Credentials instance. Default is a new instance from $options.
* @param Google_Proxy $google_proxy Optional. Google proxy instance. Default is a new instance.
* @param Profile $profile Optional. Profile instance. Default is a new instance.
* @param Token $token Optional. Token instance. Default is a new instance.
*/
public function __construct(
Context $context,
Options $options = null,
User_Options $user_options = null,
Credentials $credentials = null,
Google_Proxy $google_proxy = null,
Profile $profile = null,
Token $token = null
) {
$this->context = $context;
$this->options = $options ?: new Options( $this->context );
$this->user_options = $user_options ?: new User_Options( $this->context );
$this->credentials = $credentials ?: new Credentials( new Encrypted_Options( $this->options ) );
$this->google_proxy = $google_proxy ?: new Google_Proxy( $this->context );
$this->profile = $profile ?: new Profile( $this->user_options );
$this->token = $token ?: new Token( $this->user_options );
}
/**
* Gets the Google client object.
*
* @since 1.39.0
* @since 1.2.0 Now always returns a Google_Site_Kit_Client.
*
* @return Google_Site_Kit_Client Google client object.
*/
public function get_client() {
if ( ! $this->google_client instanceof Google_Site_Kit_Client ) {
$credentials = $this->credentials->get();
$this->google_client = Client_Factory::create_client(
array(
'client_id' => $credentials['oauth2_client_id'],
'client_secret' => $credentials['oauth2_client_secret'],
'redirect_uri' => $this->get_redirect_uri(),
'token' => $this->get_token(),
'token_callback' => array( $this, 'set_token' ),
'token_exception_callback' => function ( Exception $e ) {
$this->handle_fetch_token_exception( $e );
},
'required_scopes' => $this->get_required_scopes(),
'login_hint_email' => $this->profile->has() ? $this->profile->get()['email'] : '',
'using_proxy' => $this->credentials->using_proxy(),
'proxy_url' => $this->google_proxy->url(),
)
);
}
return $this->google_client;
}
/**
* Gets the list of currently required Google OAuth scopes.
*
* @since 1.39.0
* @see https://developers.google.com/identity/protocols/googlescopes
*
* @return array List of Google OAuth scopes.
*/
public function get_required_scopes() {
/**
* Filters the list of required Google OAuth scopes.
*
* See all Google oauth scopes here: https://developers.google.com/identity/protocols/googlescopes
*
* @since 1.39.0
*
* @param array $scopes List of scopes.
*/
$scopes = (array) apply_filters( 'googlesitekit_auth_scopes', array() );
return array_unique(
array_merge(
// Default scopes that are always required.
array(
'openid',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
),
$scopes
)
);
}
/**
* Gets the list of currently granted Google OAuth scopes for the current user.
*
* @since 1.39.0
* @see https://developers.google.com/identity/protocols/googlescopes
*
* @return string[] List of Google OAuth scopes.
*/
public function get_granted_scopes() {
return $this->user_options->get( self::OPTION_AUTH_SCOPES ) ?: array();
}
/**
* Sets the list of currently granted Google OAuth scopes for the current user.
*
* @since 1.39.0
* @see https://developers.google.com/identity/protocols/googlescopes
*
* @param string[] $scopes List of Google OAuth scopes.
*/
public function set_granted_scopes( $scopes ) {
$required_scopes = $this->get_required_scopes();
$scopes = array_values( array_unique( array_intersect( $scopes, $required_scopes ) ) );
$this->user_options->set( self::OPTION_AUTH_SCOPES, $scopes );
}
/**
* Gets the current user's full OAuth token data, including access token and optional refresh token.
*
* @since 1.39.0
*
* @return array Associative array with 'access_token', 'expires_in', 'created', and 'refresh_token' keys, or empty
* array if no token available.
*/
public function get_token() {
return $this->token->get();
}
/**
* Sets the current user's full OAuth token data, including access token and optional refresh token.
*
* @since 1.39.0
*
* @param array $token {
* Full token data, optionally including the refresh token.
*
* @type string $access_token Required. The access token.
* @type int $expires_in Number of seconds in which the token expires. Default 3600 (1 hour).
* @type int $created Timestamp in seconds when the token was created. Default is the current time.
* @type string $refresh_token The refresh token, if relevant. If passed, it is set as well.
* }
* @return bool True on success, false on failure.
*/
public function set_token( array $token ) {
// Remove the error code from the user options so it doesn't
// appear again.
$this->user_options->delete( OAuth_Client::OPTION_ERROR_CODE );
return $this->token->set( $token );
}
/**
* Deletes the current user's token and all associated data.
*
* @since 1.0.3
*/
protected function delete_token() {
$this->token->delete();
$this->user_options->delete( self::OPTION_AUTH_SCOPES );
}
/**
* Converts the given error code to a user-facing message.
*
* @since 1.39.0
*
* @param string $error_code Error code.
* @return string Error message.
*/
public function get_error_message( $error_code ) {
switch ( $error_code ) {
case 'access_denied':
return __( 'Setup was interrupted because you did not grant the necessary permissions.', 'google-site-kit' );
case 'access_token_not_received':
return __( 'Unable to receive access token because of an unknown error.', 'google-site-kit' );
case 'cannot_log_in':
return __( 'Internal error that the Google login redirect failed.', 'google-site-kit' );
case 'invalid_client':
return __( 'Unable to receive access token because of an invalid client.', 'google-site-kit' );
case 'invalid_code':
return __( 'Unable to receive access token because of an empty authorization code.', 'google-site-kit' );
case 'invalid_grant':
return __( 'Unable to receive access token because of an invalid authorization code or refresh token.', 'google-site-kit' );
case 'invalid_request':
return __( 'Unable to receive access token because of an invalid OAuth request.', 'google-site-kit' );
case 'missing_delegation_consent':
return __( 'Looks like your site is not allowed access to Google account data and can’t display stats in the dashboard.', 'google-site-kit' );
case 'missing_search_console_property':
return __( 'Looks like there is no Search Console property for your site.', 'google-site-kit' );
case 'missing_verification':
return __( 'Looks like the verification token for your site is missing.', 'google-site-kit' );
case 'oauth_credentials_not_exist':
return __( 'Unable to authenticate Site Kit, as no client credentials exist.', 'google-site-kit' );
case 'refresh_token_not_exist':
return __( 'Unable to refresh access token, as no refresh token exists.', 'google-site-kit' );
case 'unauthorized_client':
return __( 'Unable to receive access token because of an unauthorized client.', 'google-site-kit' );
case 'unsupported_grant_type':
return __( 'Unable to receive access token because of an unsupported grant type.', 'google-site-kit' );
default:
/* translators: %s: error code from API */
return sprintf( __( 'Unknown Error (code: %s).', 'google-site-kit' ), $error_code );
}
}
/**
* Handles an exception thrown when fetching an access token.
*
* @since 1.2.0
*
* @param Exception $e Exception thrown.
*/
protected function handle_fetch_token_exception( Exception $e ) {
$error_code = $e->getMessage();
// Revoke and delete user connection data on 'invalid_grant'.
// This typically happens during refresh if the refresh token is invalid or expired.
if ( 'invalid_grant' === $error_code ) {
$this->delete_token();
}
$this->user_options->set( self::OPTION_ERROR_CODE, $error_code );
if ( $e instanceof Google_Proxy_Code_Exception ) {
$this->user_options->set( self::OPTION_PROXY_ACCESS_CODE, $e->getAccessCode() );
}
}
/**
* Gets the OAuth redirect URI that listens to the callback request.
*
* @since 1.39.0
*
* @return string OAuth redirect URI.
*/
protected function get_redirect_uri() {
return add_query_arg( 'oauth2callback', '1', admin_url( 'index.php' ) );
}
}