Google OAuth2 refresh token using PHP - php

I am trying to create and save an access token that I can reference when other users in my organization (who do not have API access) log in. For instance I need to call Google Admin API to grab their orgUnit. When I get my access_token I can use this with other users but it expires after an hour and I have to re-log in with my account to get a new token.
In Short, I am not sure where or how to create the refresh token so I can save it in my datbase.
//Create Client Request to access Google API
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setClientId(CLIENT_ID);
$client->setClientSecret(CLIENT_SECRET);
$client->setRedirectUri(REDIRECT_URL);
$client->setDeveloperKey(API_KEY);
$client->setAccessType('offline');
$client->addScope("https://www.googleapis.com/auth/userinfo.email");
$client->addScope("https://www.googleapis.com/auth/admin.directory.user.readonly");
//Send Client Request
if($client->isAccessTokenExpired()){
//not doing anything here at the moment
}
$objOAuthService = new Google_Service_Oauth2($client);
//Logout
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
unset($_SESSION['code']);
$client->revokeToken();
header('Location: ' . filter_var(REDIRECT_URL, FILTER_SANITIZE_URL)); //redirect user back to page
}else if (isset($_GET['code'])) {
//Authenticate code from Google OAuth Flow
//Add Access Token to Session
$client->authenticate($_GET['code']);
$_SESSION['code'] = $_GET['code'];
$_SESSION['access_token'] = $client->getAccessToken();
header('Location: ' . filter_var(REDIRECT_URL, FILTER_SANITIZE_URL));
}
//Set Access Token to make Request
if (isset($_SESSION['access_token'])) {
$client->setAccessToken($_SESSION['access_token']);
}

Related

Google API :OAuth 2.0 authenticate return "invalid_grand" "Bad request"

I am using code examples of YouTube Api v3
I turned on YouTube Data API v3.
I create Oauth Client in the developer console
I added my url ($app->url('google.auth.test')) to allowed redirect URI
I copied the client id and secret
Then I used example code
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setApprovalPrompt('force');//read some topics - it could help
$client->setAccessType('offline');//read some topics - it could help
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var($app->url('google.auth.test'),
FILTER_SANITIZE_URL);//uri of this page
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$cred = $client->authenticate($_GET['code']);
dump($_GET['code']);
dump($cred);
dump($client->getAccessToken());
exit;
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
// This code creates a new, private playlist in the authorized user's
//some code
$_SESSION['token'] = $client->getAccessToken();
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = "
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
";
return $htmlBody;
}
After I go to to $app-url('google.auth.test')
I am being redirected to
Authorization Required
You need to authorize access before proceeding.
It is OK.
After clicking - redirect to google auth it is OK.
Accept google auth and redirect back to $app-url('google.auth.test')
I get code and my status in get request, but $client->authenticate($_GET['code']); return me error
Dump info:
I think I did not find some advanced google settings.
Thanks for answers!

Oauth 2 $client->getAccessToken() Returns Null value

I am using codeigniter MVC framework for signing in to my site using google client library. Everything is working fine except $client->getAccessToken() when google redirects with code and I do the following code. $client->getAccessToken() return null value. Here is my code for controller function one. In this function I set my credentials to create authUrl.
public function login()
{
// Include two files from google-php-client library in controller
include_once APPPATH . 'third_party/google-api-php-client/vendor/autoload.php';
// Store values in variables from project created in Google Developer Console
$client_id = 'XXXXXX';
$client_secret = 'XXXXX';
$redirect_uri = 'path/to/mysite/login/loginGoogle';
$simple_api_key = 'XXXXXXX';
// Create Client Request to access Google API
$client = new Google_Client();
$client->setApplicationName("mysite");
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->setDeveloperKey($simple_api_key);
$client->addScope("https://www.googleapis.com/auth/userinfo.email");
$authUrl = $client->createAuthUrl();
$data['authUrl'] = $authUrl;
$this->load->view('login',$data);
}
And after that when google authenticate and redirects to my redirect uri which is an other controller function which is given below. and problem is in this function.
public function loginGoogle()
{
// Include two files from google-php-client library in controller
include_once APPPATH . 'third_party/google-api-php-client/vendor /autoload.php';
$client_id = 'XXXXXX';
$client_secret = 'XXXXX';
$redirect_uri = 'path/to/mysite/login/loginGoogle';
$simple_api_key = 'XXXXXXX';
// Create Client Request to access Google API
$client = new Google_Client();
$client->setApplicationName("mysite");
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->setDeveloperKey($simple_api_key);
$client->addScope("https://www.googleapis.com/auth/userinfo.email");
$objOAuthService = new Google_Service_Oauth2($client);
// Add Access Token to Session
if(!isset($_SESSION['access_token'])){
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$token = $client->getAccessToken();
$_SESSION['access_token'] = $token;
print_r($this -> session -> userdata());exit;
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
}
// Set Access Token to make Request
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
}
// Get User Data from Google and store them in $data
if ($client->getAccessToken()) {
$userData = $objOAuthService->userinfo->get();
$data['userData'] = $userData;
$_SESSION['access_token'] = $client->getAccessToken();
}}
here in second function getAccessToken return nothing and google throws expection.
It looks like you never get the refresh token. There are two different tokens, the access token expires every few hours or so, but the refresh token is only sent the one time when the redirect asks the user for permission. It needs to be stored somewhere secure and is used in the future to refresh the access token.
Here's what my codeigniter code looks like to access the Google API (this would replace your if statements in the loginGoogle function:
if($refresh_token_accessed_from_my_database) {
//If session contains no valid Access token, get a new one
if ($client->isAccessTokenExpired()) {
$client->refreshToken($refresh_token_accessed_from_my_database);
}
//We have access token now, launch the service
$this->service = new Google_Service_Calendar($client);
}
else {
//User has never been authorized, so let's ask for the ok
if (isset($_GET['code'])) {
//Creates refresh and access tokens
$credentials = $client->authenticate($_GET['code']);
//Store refresh token for further use
//I store mine in the DB, I've seen others store it in a file in a secure place on the server
$refresh_token = $credentials['refresh_token'];
//refresh_token->persist_somewhere()
//Store the access token in the session so we can get it after
//the callback redirect
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
if (!isset($_SESSION['access_token'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$this->service = new Google_Service_Calendar($client);
}
If you are running on PLESK you might want to change the permission on /var/lib/php/session to 1777.
chmod 1777 /var/lib/php/sessions

google analytics (401) Login Required error

i am using google analytics php api to retrieve my data. on index.php i have authorization process done which works fine and i get successful login on this page i have link to another php page where i want to display all my properties so how i can post my login credentials to properties.php and create an analytics object to retrieve all the webproperties
code index.php look like this
session_start();
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_AnalyticsService.php';
$scriptUri = "http://".$_SERVER["HTTP_HOST"].$_SERVER['PHP_SELF'];
$client = new Google_Client();
$client->setAccessType('online'); // default: offline
$client->setApplicationName('XXXX');
$client->setClientId('XXXXXX');
$client->setClientSecret('XXXXX');
$client->setRedirectUri($scriptUri);
$client->setDeveloperKey('XXXXXX'); // API key
$client->setScopes('https://www.googleapis.com/auth/analytics');
$service = new Google_AnalyticsService($client);
if (isset($_GET['logout'])) { // logout: destroy token
unset($_SESSION['token']);
die('Logged out.');
}
if (isset($_GET['code'])) { // we received the positive auth callback, get the token and store it in session
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) { // extract token from session and configure client
$token = $_SESSION['token'];
$client->setAccessToken($token);
}
if (!$client->getAccessToken()) { // auth call to google
$authUrl = $client->createAuthUrl();
header("Location: ".$authUrl);
die;
}
TRY{
}
?>

Google API Oauth php permanent access

I am using the google Calendar API. This is what I want, once you give the app the permission, I can always use the app, without the need of giving access everyday. I keep hearing that I need to save the access token or use the refresh token to do what I want to do.. Here is the thing, how do you do it? How does the code look like? I've tried saving the token in a cookie, but after an hour, the access token has expired. How do I keep the user logged in?
PS: Please give me code examples with explanations.
Here is my code (using CakePHP):
$client = new Google_Client();
$client->setApplicationName("Wanda3.0 Agenda");
$cal = new Google_CalendarService($client);
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);
}
if (isset($_SESSION['token'])) { $client->setAccessToken($_SESSION['token']); }
if ($client->getAccessToken()) {
/************* Code entry *************/
}else{
/************* Not connected to google calendar code *************/
$authUrl = $client->createAuthUrl();
$returnArr = array('status' => 'false', 'message' => "<a class='login' href='$authUrl'>Connect Me!</a>");
return $returnArr;
}
Ok, after waiting for a few days, the suggestion from Terry Seidler(comments below) made it all happen! Here is my piece of code on how to automaticly refresh the access token without autenticating each time using cookies.
(NOTICE: It's safer to save the refresh token in your database)
This is the magic (using cookies):
$client = new Google_Client();
$client->setApplicationName("Wanda3.0 Agenda");
$cal = new Google_CalendarService($client);
$client->setAccessType('offline');
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);
}
//Where the magic happends
if (isset($_SESSION['token'])) {
//Set the new access token after authentication
$client->setAccessToken($_SESSION['token']);
//json decode the session token and save it in a variable as object
$sessionToken = json_decode($_SESSION['token']);
//Save the refresh token (object->refresh_token) into a cookie called 'token' and make last for 1 month
$this->Cookie->write('token', $sessionToken->refresh_token, false, '1 month');
}
//Each time you need the access token, check if there is something saved in the cookie.
//If $cookie is empty, you are requested to get a new acces and refresh token by authenticating.
//If $cookie is not empty, you will tell the client to refresh the token for further use,
// hence get a new acces token with the help of the refresh token without authenticating..
$cookie = $this->Cookie->read('token');
if(!empty($cookie)){
$client->refreshToken($this->Cookie->read('token'));
}
And thats it! IF you have any questions, feel free to leave a comment below and I will answer the best I can. Goodluck and Cheers!
Instead of using cookies and sessions you should save it in the database and use it.
A similar implementation for drupal site is at Google OAuth2 sandbox at http://drupal.org/sandbox/sadashiv/1857254 This module allows you to handle the authentication from admin interface of drupal. You can then use the fetched access token from google and then use the api function of google_oauth2_account_load or google_oauth2_client_get to get the Google_Client and carry your api call.
Much the same as hope industries but after testing I only wanted to refresh the token when I had to. Full source just change the keys etc at the top:
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
session_start();
$client = new Google_Client();
$client->setApplicationName("Google Calendar PHP Starter Application");
// Visit https://code.google.com/apis/console?api=calendar to generate your
// client id, client secret, and to register your redirect uri.
$client->setClientId('your_id');
$client->setClientSecret('your_secret');
$client->setRedirectUri("http://localhost/your_redirect.php");
$client->setDeveloperKey('your_key');
$cal = new Google_CalendarService($client);
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . $query_string);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);//update token
//json decode the session token and save it in a variable as object
$sessionToken = json_decode($_SESSION['token']);
//Save the refresh token (object->refresh_token) into a cookie called 'token' and make last for 1 month
if (isset($sessionToken->refresh_token)) { //refresh token is only set after a proper authorisation
$number_of_days = 30 ;
$date_of_expiry = time() + 60 * 60 * 24 * $number_of_days ;
setcookie('token', $sessionToken->refresh_token, $date_of_expiry);
}
}
else if (isset($_COOKIE["token"])) {//if we don't have a session we will grab it from the cookie
$client->refreshToken($_COOKIE["token"]);//update token
}
if ($client->getAccessToken()) {
$calList = $cal->calendarList->listCalendarList();
print "<h1>Calendar List</h1><pre>" . print_r($calList, true) . "</pre>";
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Select a calendar!</a>";
}

Google+ get userID using e-mail?

I want to know if it is possible to get the "userId" value using the Google+ api, in order to display a link to some specific user profile. For better explanation, I have a PHP application and there is a panel where I can view the existing users in my database. So, when detailing a specific user, I want to show a Google+ badge which will link to that user's Google+ profile. I don't have the "userId", but still have access to his email address. Any suggestions?
There is no endpoint that you can hit to convert an email address into a Google+ userId.
However, you can use the REST API to determine the Google+ userId of the currently logged in user. This will require the user to grant you access to their identity on Google+ via OAuth. To do this use the people get endpoint with me as the userId. You can try this out on the API Explorer to observe what the user experience with the OAuth dialog will be like.
Here's some code lifted from the PHP starter project that illustrates everything you need to fetch the userId of the current user:
if (ini_get('register_globals') === "1") {
die("register_globals must be turned off before using the starter application");
}
require_once 'google-api-php-client/src/apiClient.php';
require_once 'google-api-php-client/src/contrib/apiPlusService.php';
session_start();
$client = new apiClient();
$client->setApplicationName("Google+ PHP Starter Application");
// Visit https://code.google.com/apis/console to generate your
// oauth2_client_id, oauth2_client_secret, and to register your oauth2_redirect_uri.
$client->setClientId('insert_your_oauth2_client_id');
$client->setClientSecret('insert_your_oauth2_client_secret');
$client->setRedirectUri('insert_your_oauth2_redirect_uri');
$client->setDeveloperKey('insert_your_developer_key');
$client->setScopes(array('https://www.googleapis.com/auth/plus.me'));
$plus = new apiPlusService($client);
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
}
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['access_token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['access_token'])) {
$client->setAccessToken($_SESSION['access_token']);
}
if ($client->getAccessToken()) {
$me = $plus->people->get('me');
// Do stuff with the id
echo $me['id'];
// The access token may have been updated lazily.
$_SESSION['access_token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
}

Categories