I am using Google API to allow my users to send emails from my website. Emails are sent very well but as strange as it can appear I have trouble getting the users' information and especially his email.
Here is the code I wrote:
$client = new Google_Client();
$client->addScope(Google_Service_Gmail::GMAIL_READONLY);
$client->addScope(Google_Service_Gmail::GMAIL_LABELS);
$client->addScope(Google_Service_Gmail::GMAIL_MODIFY);
$client->setAuthConfig(__DIR__.'/credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
$accessTokenLive = $client->fetchAccessTokenWithRefreshToken($refreshToken);
$client->setAccessToken($accessTokenLive);
$oauth = new Google_Service_Oauth2($client);
$accessToken = $client->getAccessToken();
$userData = $oauth->userinfo->get();
var_dump($userData);
The $refreshToken is fetched from the database
I am getting an error message:
Request is missing the required authentication credential. Expected OAuth 2 access token, login cookie or another valid authentication credential.
I understand $oauth->userinfo->get() may need OAuth credentials but I can't find where to get them and most answers concerning the same issues comes out with the script above. Plus Google's API documentation says the scope is right.
I really struggle to understand how it works.
Related
I am building a portal where multiple users can log in to their multiple Gmail accounts. I have successfully retrieved the token value, However, I want to store that in my database but I am unable to store it.
Below is the code I am using:
function mInititalize(){
$client = new Google_Client();
$client->addScope('https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://mail.google.com/');
$client->setClientId(Config('gmail.client_id'));
$client->setClientSecret(Config('gmail.client_secret'));
$client->setRedirectUri('http://localhost:81'.Config('gmail.redirect_url'));
$loginURL = $client->createAuthUrl();
return redirect($loginURL);
}
After Redirection or user login
function mGetToken(){
$token = $client->fetchAccessTokenWithAuthCode( 'code'); // here i get the 'code' from login URL
I pass this code to get token I successfully get token
$oAuth = new Google_Service_Oauth2( $client);
$userData = $oAuth->userinfo_v2_me->get(); // get current user detail
}
I want to store $token value in database, but I am getting error message
>Serialization of 'Closure' is not allowed
Please anyone help me to solve this issue. Thanks.
I would suggest storing OAuth credential information for the Google API, not in your database, but through the API itself. If you're intending to use it any authentication manner, you'll run into problems, as the docs state:
Access tokens periodically expire and become invalid credentials for a related API request. Google Identity Platform: Using OAuth 2.0 for Web Server Applications
But, the same docs also show a way that you can set or retrieve the token natively within the API. Since it's data relating to google's auth'ing process, and since it might go stale if you store it, it seems best to just let them handle it and work with the API. The same source:
If you need to apply an access token to a new Google_Client object—for example, if you stored the access token in a user session—use the setAccessToken method:
$client->setAccessToken($access_token);
$client->getAccessToken();
Having a problem with the refreshToken procedure with Google API, upon an expired token is experienced the refreshToken doesn't get an AccessToken. I've already saved the refresh token to the db at this point.
$client = new Google_Client();
$client->setApplicationName("APP NAME");
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setAccessType('offline');
$client->setScopes(array('https://www.googleapis.com/auth/calendar'));
$client->setAccessToken( json_encode($access_token_from_db) );
if ( $client->isAccessTokenExpired() ) :
$client->refreshToken($refresh_token_from_db);
$new_access_token = $client->getAccessToken();
print_r($access_token);
//save to db -- but this fails
endif;
After running this the new access token is still empty. Even if I setAccessToken to the now expired token prior to checking expiration the same problem persists.
There doesn't seem to be a straight forward example on a state after a refreshToken has already been saved.
In my application we would cron job to send updates to a user's calendar based on actions (if necessary to understand the application purpose).
The reason this answer doesn't seem correct to me:
How to refresh token with Google API client?
is because it's not using the $client->isAccessTokenExpired() method, plus isn't a clean solution, the script should be very minimal and small to complete the task. In theory:
setAccessToken to the one given on authorization
if expired (via function), use the refresh to access a new token
save the token and continue
While the above example had similar functions it's a 2013 answer and may work but isn't the best way to do this I believe.
My failure was because I messed up my own clientID, but I'm posting this script here anyways because it took me forever to find the correct answer that was small, efficient and effective (the below is strictly after a token and refresh have been already saved to your db):
$client = new Google_Client();
$client->setApplicationName('APP NAME');
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setAccessType('offline');
$client->setScopes(array('https://www.googleapis.com/auth/calendar'));
// my app is for google calendar.
$access_token_from_db = 'XXXXXX';
$refresh_token_from_db = 'XXXXX';
$_tokenArray['access_token'] = $access_token_from_db
$client->setAccessToken( $_tokenArray );
//check if token expired:
if ( $client->isAccessTokenExpired() ) :
$client->refreshToken($refresh_token_from_db);
$new_access_token = $client->getAccessToken();
//now save your new access token to your db
endif;
I am using youtube API for scheduling live events for user in my application.
Once the user logged in my application i need to logged in the same user to our business google account(One google account for all user) without giving login credentials. and to get access token for scheduling the live events.
Is it possible to login the user into google account without giving login credentials(User will not feel he is login to another account).
Is it feasible with PHP?.Please give one example to get access token for youtube API access.
I used the following code for getting access token but service account can't access the youtube service.
My code for getting access token using service account:
<?php
require_once 'Google/autoload.php';
session_start();
$client_id = '395540674667-p64tdfqdsfsdfdsf#dsfd.com';
$Email_address = '54564-drgfdg1#developer.gserviceaccount.com';
$key_file_location = 'Youtube API-5czxczxc86.p12';
$client = new Google_Client();
$client->setApplicationName("Youtube API");
$key = file_get_contents($key_file_location);
// seproate additional scopes with a comma
$scopes = array('https://www.googleapis.com/auth/sqlservice.admin','https://www.googleapis.com/auth/plus.login','https://www.googleapis.com/auth/youtube');
$cred = new Google_Auth_AssertionCredentials($Email_address,
$scopes,
$key);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
//print_r($client);
echo $client->getAccessToken();
?>
I am expecting the answer is something like this.Any one please help
you example about Youtube api, first:
select credentials to your api project from here:
https://console.cloud.google.com/home/dashboard?project= with your project
also you need to have the api enable because google told us "Some APIs are enabled automatically."
when you select:
https://console.cloud.google.com/apis/api/youtube/ with Go to Credentials you have some option into modal window this will help
also.
the php code seem to be ok but also I think you will change after you learn more about Credentials settings.
I have a task to import video details of videos, uploaded on YouTube.
I have an account, that is the video owner. I have setup credentials in the console: https://console.developers.google.com/project/XXXXX/apiui/credential. I have created OAuth Service Account there.
Later in the script I am using the code from documentation (v3 version of the API):
$credentials = new Google_Auth_AssertionCredentials(
$clientEmail,
[
'https://www.googleapis.com/auth/youtube',
'https://www.googleapis.com/auth/youtube.force-ssl',
'https://www.googleapis.com/auth/youtube.readonly',
'https://www.googleapis.com/auth/youtubepartner',
],
$privateKeyContents
);
$this->client->setAssertionCredentials($credentials);
/** #var Google_Auth_OAuth2 $auth */
$auth = $this->client->getAuth();
if ($auth->isAccessTokenExpired()) {
$auth->refreshTokenWithAssertion();
}
Authentication works ok. I've attached logger to Google Client and I can see Authorization: Bearer XXXXXXX header passed with each request.
But the problem is, that it seems, YouTube does not recognize this authentication as an authentication of an actual resource owner. For example, if I request Video Snippet, it is returned without tags (tags can be seen only by owner on some reason).
If I make the same request from here https://developers.google.com/youtube/v3/docs/videos/list?hl=ru it works flawlessly.
What can be the problem?
The request in logs looks like this:
[2015-06-08 14:50:02] name.DEBUG: OAuth2 authentication [] []
[2015-06-08 14:50:02] name.DEBUG: cURL request {"url":"https://www.googleapis.com/youtube/v3/playlists?part=id%2Csnippet&channelId=XXXXXXXXXXXX&maxResults=50","method":"GET","headers":{"authorization":"Bearer ya29.XXXXX-XXXXXX","accept-encoding":"gzip"},"body":null} []
This differs from what I can see if tracing the request Google Javascript client makes on Documentation page. The domain is different, Javascript client passes more headers etc.
How do I make it work with PHP?
You should add onBehalfofContentOwner parameter to your request to show yourself as the content owner.
You seem to have been using Google Service Account credentails for authentication. The API call needs to be made after authenticating as "Client ID for web application" rather than a service account. After you have created a new set of credentials for web application, authenticate as follows:
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);//This Uri should match exactly to what you had given in Google Developer Console while generating Client ID/Secret
// 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.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
Hope this resolves your problem.
I am trying to get a refresh token for the Google API's, using the PHP SDK. I am authenticating the user with Javascript, retrieving a code, and exchanging it for an access_token server side, but this doesn't grant me an access token. What am I doing wrong? Here is the code I use:
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->addScope('https://www.googleapis.com/auth/plus.me');
$client->addScope('https://www.google.com/m8/feeds');
$client->setRedirectUri('postmessage');
$client->setAccessType('offline');
if (isset($_REQUEST['code'])) {
$client->authenticate($_REQUEST['code']);
if ($client->getAccessToken()) {
$_SESSION['access_token'] = $client->getAccessToken();
$token_data = $client->verifyIdToken()->getAttributes();
$result['data']=$token_data;
$result['access_token']=json_decode($_SESSION['access_token']);
}
}
debug($result); //my own function, var_dumps the content of an array
Here is the result of the array:
$result['access_token'] contains:
access_token: TOKEN
created: 1434380576
expires_in: 3594
id_token: IDTOKEN
token_type:"Bearer"
If I am not mistaken the first access token should also contain the refresh token, what am I doing wrong?
First check the settings in the developer console of Google to see if your RedirectUri is the same and that the API is activated (although if you already got that .json, then I assume it is.
You have to go through the Google Auth Prompt Screen at least 1 time to get a refresh token in your .json, and if your RedirectUri is taking you nowhere, you won't be able to get your refresh token or even the access validated.
You can also try a service account if you're doing small file transactions and don't need a user validation for the process of your script. Good Luck.
The problem was that I had to specify that I want offline access in the authentication process, the client side... The Google API's are horribly documented!!!