I'll like to update the title, short description and full description of my apps in google developper console.
I cannot do it in PHP, I have found some examples in python but I need in PHP.
Here is what I've done till now :
function updateListing($configFileJSON) {
echo "Updating Listings"."\n";
$packageName = 'com.mycompany.myapp';
$client = new Google_Client();
$client->setApplicationName($packageName);
$client->setClientId('100......usercontent.com');
$key = "Rdhmg......5_t";
$client->setClientSecret($key);
$client->setScopes(array('https://www.googleapis.com/auth/androidpublisher') );
try {
$service = new Google_Service_AndroidPublisher($client);
$app_edit = new Google_Service_AndroidPublisher_AppEdit();
$edits = $service->edits;
$edit_request = $edits->insert($packageName,$app_edit);
$edit = $edit_request->execute();
$editId = $edit->getId();
echo ("Created edit with id: $editId");
$listing = $service->listings;
$listing.setTitle("WWW");
$listing.setFullDescription("WWW");
$listing.setShortDescription("WWW");
// $listing.setVideo("WWW");
$updateListingsRequest = $edits->listings()->update($packageName,$editId,"af", $listing);
$updatedUsListing = $updateListingsRequest->execute();
echo("Created new AF app listing with title: " . $$updatedUsListing->getTitle());
} catch (Exception $e) {
var_dump( $e->getMessage() );
}
echo "ENDING"."\n";
}
I know there is still some code missing, but until now I get :
string(238) "{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
the sample in python is:
def main(argv):
# Authenticate and construct service.
service, flags = sample_tools.init(
argv,
'androidpublisher',
'v2',
__doc__,
__file__, parents=[argparser],
scope='https://www.googleapis.com/auth/androidpublisher')
# Process flags and read their values.
package_name = flags.package_name
try:
edit_request = service.edits().insert(body={}, packageName=package_name)
result = edit_request.execute()
edit_id = result['id']
listing_response_us = service.edits().listings().update(
editId=edit_id, packageName=package_name, language='af',
body={'fullDescription': 'Dessert trunk truck',
'shortDescription': 'Bacon ipsum',
'title': 'App Title US'}).execute()
print ('Listing for language %s was updated.'
% listing_response_us['language'])
listing_response_gb = service.edits().listings().update(
editId=edit_id, packageName=package_name, language='am',
body={'fullDescription': 'Pudding boot lorry',
'shortDescription': 'Pancetta ipsum',
'title': 'App Title UK'}).execute()
print ('Listing for language %s was updated.'
% listing_response_gb['language'])
commit_request = service.edits().commit(
editId=edit_id, packageName=package_name).execute()
# print 'Edit "%s" has been committed' % (commit_request['id'])
except client.AccessTokenRefreshError:
print ('The credentials have been revoked or expired, please re-run the '
'application to re-authorize')
if __name__ == '__main__':
main(sys.argv)
what I'm missing in the authentificate part? anyone have a sample of updating app listing in PHP?
Thanks
Your code appears to be missing the entire authentication section.
Oauth2Authentication.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
oauth2callback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
Related
I'm using the latest version of the Google API Client PHP SDK (v2.11) to request an OAuth2 access token.
While retrieving an access token, I can see that the expires_in value is missing from the response, which leads to a PHP error when calling isAccessTokenExpired() later on:
Step 1 - Retrieve an access and refresh token
...
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
var_dump($client->getAccessToken());
...
Result
array(1) { ["access_token"]=> string(163) "xxxxxxxxxxxxxxxxxxx" }
It seems that both the expires_in and created columns are missing from this answer.
Step 2 - Let's check if the Access token has expired and needs to be refreshed
$client->setAccessToken($_SESSION['access_token']);
if ($client->isAccessTokenExpired())
{
$client->refreshToken($_SESSION['refresh_token']);
$_SESSION['access_token'] = $client->getAccessToken();
}
Result
Warning: Undefined array key "expires_in" in
/var/www/admin/vendor/google/apiclient/src/Client.php on line 554
This is the code I use. The library should be handling this for you.
Oauth2Callback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
Oauth2Authentication.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
?>
My API response was missing expires_in due to retrieving the tokens twice in my redirect.php script (called after the user has been authenticated).
As described here, the OAuth refresh token as well as expires_in value are provided to you only during the first authorization. Adding a consent prompt also helped to address this issue.
If you are doing some testing and need to reset the authorization you gave, you can do it here: https://myaccount.google.com/permissions
Here's the full script, which is now working:
<?php
include(__DIR__.'/vendor/autoload.php');
$client = new Google_Client();
$client->setAccessType('offline');
$client->setClientId(GOOGLE_OAUTH_CLIENT_ID);
$client->setClientSecret(GOOGLE_OAUTH_CLIENT_SECRET);
$client->setRedirectUri(BASE_URL.'/redirect.php');
$client->addScope('email');
$client->addScope('profile');
$client->setPrompt('consent');
if (isset($_GET['code']) && !empty($_GET['code']))
{
$client->authenticate($_GET['code']);
if ($client->getAccessToken())
{
$google_oauth = new Google_Service_Oauth2($client);
$google_account_info = $google_oauth->userinfo->get();
if (!isset($google_account_info->hd) || $google_account_info->hd != 'mydomain.com')
die('This domain name has not been authorized.');
else
{
$redirect_uri = BASE_URL.(isset($_GET['state']) ? $_GET['state'] : '/');
$_SESSION['picture'] = $google_account_info->picture;
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
$_SESSION['token_expiration'] = time() + 3600;
header('Location: '.filter_var($redirect_uri, FILTER_SANITIZE_URL));
exit;
}
}
}
It includes a domain check (i.e. replace mydomain.com by your own domain) as well as a referrer callback (i.e. populate state on your login page with the referrer first).
i have successfully integrated google api login and logout and both are working fine but after i logged in and try to refresh the webpage .. it shows me the below error-
Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://oauth2.googleapis.com/token resulted in a 400 Bad Request response: { "error":
"invalid_grant", "error_description": "Bad Request" } in
C:\xamppNew\htdocs\realestate\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:113 Stack
trace: #0 C:\xamppNew\htdocs\realestate\vendor\guzzlehttp\guzzle\src\Middleware.php(69):
GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request),
Object(GuzzleHttp\Psr7\Response), NULL, Array, NULL) #1
C:\xamppNew\htdocs\realestate\vendor\guzzlehttp\promises\src\Promise.php(204):
GuzzleHttp\Middleware::GuzzleHttp{closure}(Object(GuzzleHttp\Psr7\Response)) #2
C:\xamppNew\htdocs\realestate\vendor\guzzlehttp\promises\src\Promise.php(153):
GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), NULL) #3
C:\xamppNew\htdocs\realestate\vendor\guzzlehttp\promises\src\TaskQueue.php(48):
GuzzleHttp\Promise\Promise::GuzzleHttp\Promise{closure}() #4 C:\xamppNew\ht in
C:\xamppNew\htdocs\realestate\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php on line 113
My config.php -
<?php
session_start();
require_once 'vendor/autoload.php';
$google_client = new Google_Client();
$google_client->setAccessType('offline');
$google_client->setClientId('client key');
$google_client->setClientSecret('client secret key');
$google_client->setRedirectUri('http://localhost/realestate/index.php');
$google_client->addScope('email');
$google_client->addScope('profile');
?>
My index.php google api session codes-
<?php
include('config.php');
$login_button = '';
if(isset($_GET["code"]))
{
$token = $google_client->fetchAccessTokenWithAuthCode($_GET["code"]);
if(!isset($token['error']))
{
$google_client->setAccessToken($token['access_token']);
$_SESSION['access_token'] = $token['access_token'];
$google_service = new Google_Service_Oauth2($google_client);
$data = $google_service->userinfo->get();
if(!empty($data['given_name']))
{
$_SESSION['user_first_name'] = $data['given_name'];
}
if(!empty($data['family_name']))
{
$_SESSION['user_last_name'] = $data['family_name'];
}
if(!empty($data['email']))
{
$_SESSION['user_email_address'] = $data['email'];
}
if(!empty($data['gender']))
{
$_SESSION['user_gender'] = $data['gender'];
}
if(!empty($data['picture']))
{
$_SESSION['user_image'] = $data['picture'];
}
}
}
if(!isset($_SESSION['access_token']))
{
$login_button = '<a href="'.$google_client->createAuthUrl().'">Login With
Google</a>';
}
?>
//this is for testing purpose
<?php if($login_button == '') {echo '<h3><b>Name :</b>
'.$_SESSION['user_first_name'].' '.$_SESSION['user_last_name'].'</h3>';
echo '<h3><a href="logout.php">Logout</h3>
</div>'; }?>
//this is the login button-
<?php echo '<a class="btn connect-google">'.$login_button . '</a>'; ?>
My logout.php-
<?php
include('config.php');
$accesstoken=$_SESSION['access_token'];
//Reset OAuth access token
$google_client->revokeToken($accesstoken);
//Destroy entire session data.
session_destroy();
//redirect page to index.php
header('location:index');
?>
I have no idea how why it is happening and how to fix this. Btw after i logged in though google api in my website and refresh the page , it should refresh successfully while staying logged in . But it shows me the error and when i click back it takes to me google login page again.
I think your issue is that your not using your refresh token properly
oauth2callback.php
Notice how when the code is returned that i am storing both the access token and the refresh token into the session.
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
Oauth2Authentication.php
Then check this to see how i test if the access token is expired and if it is i use the refresh token to fetch a new one.
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
userinfo
Also you should consider going though the People api instead of the userinfo endpoint its much more stable when requesting user profile information, as you are already requesting email and profile scopes you should already have access.
I am having an issue with authorizing some requests and I am getting a 401 "Invalid Credentials" error. The application flow is as follows. The user logs in my website using the Google sign in button. I am using the offline access parameter and I am saving the refresh token in the session. After the user has logged in I am trying to retrieve all of their playlists (public and private) from their YouTube account.
$client->setScopes('https://www.googleapis.com/auth/youtube.readonly');
if (isset($_SESSION['googletoken']['refresh_token'])){
$client->setAccessToken($_SESSION['googletoken']['refresh_token']);}
$tokenSessionKey = $client->prepareScopes();
$params = [
'maxResults' => 1,
'mine' => true
];
try{
$queryParams = [
'maxResults' => 1,
'mine' => true
];
$listResponse = $youtube->playlists->listPlaylists('snippet', $queryParams);
You are setting your access token with the refresh token You should be using
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
Oauthcallback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
Oauth2Authncation.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
I am reading calendar events successfully, but when the access token expires, I cannot refresh it. Up until now, I have been getting a new access token but this doesn't seem correct. I would rather refresh it properly.
I receive this error :
refresh token must be passed in or set as part of setAccessToken
From events.php
function GetEvents()
{
$client = new \Google_Client();
$credentialsPath = '/cfg/GoogleClientSecret.json';
$client->setAuthConfig($credentialsPath);
$client->addScope(\Google_Service_Calendar::CALENDAR_READONLY);
$client->setAccessType('offline');
if (isset($_SESSION['access_token']) && $_SESSION['access_token'])
{
$client->setAccessToken($_SESSION['access_token']);
if ($client->isAccessTokenExpired())
{
$refreshTokenSaved = $client->getRefreshToken();
/**** This line fails ****/
$client->fetchAccessTokenWithRefreshToken($refreshTokenSaved);
/*************************/
$accessTokenUpdated = $client->getAccessToken();
$accessTokenUpdated['refresh_token'] = $refreshTokenSaved;
//Need to do more here once i have the new access token.
}
ReadThroughEvents($client);
}
else
{
$redirect_uri = 'oauthcallback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
oauthcallback.php
require 'google-api-php-client-2.4.0 2/vendor/autoload.php';
session_start();
$client = new \Google_Client();
$client->setAuthConfigFile('/cfg/GoogleClientSecret.json');
$callbackuri = 'oauthcallback.php';
$client->setRedirectUri($callbackuri);
$client->addScope(Google_Service_Calendar::CALENDAR_READONLY);
if (! isset($_GET['code']))
{
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
}
else
{
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'events.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
fetchAccessTokenWithRefreshToken should work assuming that the refresh token you are sending it is in fact a refresh token and not null or something. I would try and print it out so that you can see its actually a value.
Here is my code.
oauth2callback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
Oauth2Authentication.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Following the Google documentation for Web Server PHP flow located here, I was able to successfully prompt user login with oauth2callback.php. However, returning to the original site after authentication throws an internal server error 500 and does not display the GA results from profile obtained as intended.
How do I know what caused the issue?
Note: Code is taken directly from Google Documentation for Web Server PHP flow with minor adjustments to my own project's parameters.
testoauth.php
<?php
// Load the Google API PHP Client Library.
require_once '../application/third_party/vendor/autoload.php';
// Start a session to persist credentials.
session_start();
// Create the client object and set the authorization configuration
// from the client_secretes.json you downloaded from the developer console.
$client = new Google_Client();
$client->setAuthConfig('../application/views/dashboard/client_secret_file.json');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Create an authorized analytics service object.
$analytics = new Google_Service_Analytics($client);
// Get the first view (profile) id for the authorized user.
$profile = getFirstProfileId($analytics);
// Get the results from the Core Reporting API and print the results.
$results = getResults($analytics, $profile);
printResults($results);
}
else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '../application/views/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
function getFirstProfileId($analytics) {
// Get the user's first view (profile) ID.
// Get the list of accounts for the authorized user.
$accounts = $analytics->management_accounts->listManagementAccounts();
if (count($accounts->getItems()) > 0) {
$items = $accounts->getItems();
$firstAccountId = $items[0]->getId();
// Get the list of properties for the authorized user.
$properties = $analytics->management_webproperties
->listManagementWebproperties($firstAccountId);
if (count($properties->getItems()) > 0) {
$items = $properties->getItems();
$firstPropertyId = $items[0]->getId();
// Get the list of views (profiles) for the authorized user.
$profiles = $analytics->management_profiles
->listManagementProfiles($firstAccountId, $firstPropertyId);
if (count($profiles->getItems()) > 0) {
$items = $profiles->getItems();
// Return the first view (profile) ID.
return $items[0]->getId();
} else {
throw new Exception('No views (profiles) found for this user.');
}
} else {
throw new Exception('No properties found for this user.');
}
} else {
throw new Exception('No accounts found for this user.');
}
}
function getResults($analytics, $profileId) {
// Calls the Core Reporting API and queries for the number of sessions
// for the last seven days.
return $analytics->data_ga->get(
'ga:' . $profileId,
'7daysAgo',
'today',
'ga:sessions');
}
function printResults($results) {
// Parses the response from the Core Reporting API and prints
// the profile name and total sessions.
if (count($results->getRows()) > 0) {
// Get the profile name.
$profileName = $results->getProfileInfo()->getProfileName();
// Get the entry for the first entry in the first row.
$rows = $results->getRows();
$sessions = $rows[0][0];
// Print the results.
print "<p>First view (profile) found: $profileName</p>";
print "<p>Total sessions: $sessions</p>";
} else {
print "<p>No results found.</p>";
}
}
?>
oauth2callback.php
<?php
// Load the Google API PHP Client Library.
require_once '../application/third_party/vendor/autoload.php';
// Start a session to persist credentials.
session_start();
// Create the client object and set the authorization configuration
// from the client_secrets.json you downloaded from the Developers Console.
$client = new Google_Client();
$client->setAuthConfig('../application/views/dashboard/client_secret_file.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '../application/views/oauth2callback.php');
$client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '../application/views/testoauth.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
Its hard to know what could be wrong with your code without you debugging your way though it. It is possible that that code has not been updated and the library has changed. This is the code from my sample project it was generated recently. There is a Read men on how to use the samples here
Oauthcallback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
Oauth2Authentication.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Then you can check my sample project for more examples here is one on accountsummiries.list