Issue with Google-API-PHP Client, getting error when running the quick start script - google-drive-api

I am facing an issue with quickstart php script here: https://developers.google.com/drive/v2/web/quickstart/php
When I run the script first time, it executes perfectly and the access token is stored in a file called: drive-php-quickstart.json
When I run the script second time, it gives me the error:
Error start:
Notice: Undefined index: expires_in in \google-api-php-client\src\Google\Client.php on line 485
Fatal error: Uncaught exception 'LogicException' with message 'refresh token must be passed in or set as part of setAccessToken' in
Error end:
My assumption is that access token been saved in the file is not in the right format.
Current format:
ya29.CODE-oN_Bearer36001/_ANOTHER-CODE-ANOTHER_ANOTHER_CODE
As you can see, it does not contain the variable "expires_in"
Any suggestions where I am going wrong ? I am running the script as it is, with no modifications.

I've debugged it.... The person who wrote it made a mistake by not calling json_encode before writing the auth result to the token.json file.
You can fix it by adding json_encode on line 45.
So...
file_put_contents($credentialsPath, $accessToken);
...should be:
file_put_contents($credentialsPath, json_encode($accessToken));
I've submitted feedback so hopefully it'll be fixed.
edit: same issue happens for the token refresh call in that same method
edit2: Here's my related comment in a Github discussion and an answer from Google: https://github.com/google/google-api-php-client/issues/263#issuecomment-186557360
I suggested something along the following lines:
if ($client->isAccessTokenExpired()) {
$refreshToken = $client->getRefreshToken();
$client->refreshToken($refreshToken);
$newAccessToken = $client->getAccessToken();
$newAccessToken['refresh_token'] = $refreshToken;
file_put_contents($credentialsPath, json_encode($newAccessToken));
}
Instead of:
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->refreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, $client->getAccessToken());
}

Google has updated their PHP Quickstart, with an improved method to handle this:
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}

Related

Postman Canary 8.0.0-canary01 not saving environment variables

Today I upgraded my Postman to the latest version, going from PostmanCanary 7.37.0-canary01 to 8.0.0-canary01.
I used to run a login request and save the returned access token to my environment variables with this script:
response = JSON.parse(responseBody);
access_token = response.access_token;
postman.setEnvironmentVariable("access_token",access_token);
to process this response :
{
"token_type": "Bearer",
"expires_in": "3599",
"ext_expires_in": "3599",
"expires_on": "1610147694",
"not_before": "1610143794",
"resource": "https://xxxxxxxxxxx.crm.dynamics.com/",
"access_token": "eyJ0eXAiOiJKV1QxxxxxxxxxxxxxxxI1NiIsIng1dCI6IjVPZjlQNUY5xxxxxxxxxxxxxxxxxxxxxx1EayIsxxxxZCI6IjxxxxxxxxxxxxNDd0NtxxxxxxxxxEREUS1Exxxx.xxxxxxxxxxxxxxxwczovL2RxxxxkZXZxxxxxxxxxxxxxxxxxxxxxcy5jb20vIiwiaXNxxxxxxxxxxxxxxxxzdHMud2luZG93cy5uZXQvNTBmOGZjYzxxxxxxxxxxxxxxxxxxxxxtMzZlZDU3YzdjOGEyLyIsImlhdCI6MTYxMDE0Mzc5NCwibmJmIjoxNjEwMTQzNzk0LCJleHAiOjE2MTAxNDc2OTQsImFpbyI6IkUySmdZQWc0bjN2L1o4VE5HT20zdnRQMStMZGFBZ0E9IiwiYXBwaWQiOiI4ZTc3ZDkzZi05MmY1LTRhMWYtOWY1OS1iZGY4ZGNkYTNkY2IiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81MGY4ZmNjNC05NGQ4LTRmMDctODRlYi0zNmVkNTdjN2M4YTIvIiwib2lkIjoiYmJmZjA5OTQtZGQyNi00Nzg5LThlMjktMTc5OTIwOWI0ZDMxIiwicmgiOiIwLkFBQUF4UHo0VU5pVUIwLUU2emJ0VjhmSW9qX1pkNDcxa2g5S24xbTktTnphUGNzTkFCdy4iLCJzdWIiOiJiYmZmMDk5NC1kZDI2LTQ3ODktOGUyOS0xNzk5MjA5YjRkMzEiLCJ0aWQiOiI1MGY4ZmNjNC05NGQ4LTRmMDctODRlYi0zNmVkNTdjN2M4YTIiLCJ1dGkiOiJjZXJzaGlldGxFeU15Q1c2MVFWTUFBIiwidmVyIjoiMS4wIn0.EXV9P_DZIdVbTUK4PY6VcyrUmUx752ZA9MGr5BJ7xxxxxxxxxxxx-xxxxxxxxxX5wgidfGfoNklllZuoJVTi91jtnKP2T9Q-XFShpXhexDdCgOvMe9ZOOd0vOb11of1YPl37GKILtHikT3oPvKfUjBhOjZkFJo6F7pKeuxa3XiD_3WM1eCurVzuaG9iME94mFXb3HNTgUrWw9mPEqDwVzfxxxxx-xxxx-xxxxy0lw-2EcqpEYk7fqHUOTPUfAj2426zVV7ITfFPLdN08c4OND336sXpKjEFa5c7Buyk1dc24nawqJwCoKve1DaZAwPwljZKhGIIW4rd-1nitik2xWg"
}
Even if the environment variables did not exist prior to the call, this script would create them and set values. If I opened the environment variables, it would be listed.
After the upgrade, this no longer works. My subsequent requests kept failing because an old access_token was still there as it was not getting updated. I deleted the old access_token and confirmed that the access_token is now no longer being created.
I read about the resulting parsed JSON causing issues for other people because it is not text. I don't truly believe this to be the issue, mine is a single value, not a structure nor an array, but decided to play it safe and stringify it. Following the current documentation, I changed my script to :
response = JSON.parse(responseBody);
access_token = response.access_token;
console.log (access_token); // I can see the token in the console - parsing executed correctly
pm.environment.set("access_token",JSON.stringify(access_token)); // setting the environment variable
console.log(pm.environment.get("access_token")); // getting the exact same environment variable I have just set - I can see this on the console as well
console.log("WTF?!?!?"); // Self explanatory - added at the end to ensure all instructions in the script are read and executed - I see this every time as well
This does not work either (with or without stringify) and gives me the same results. Everything seems fine on the console, but when I look at my environment variables, access_token is not present although I can access it during the execution of the test script. Afterward, it is gone.
At this point I'm frustrated and at a loss - have anyone else seen similar behavior or am I missing something stupidly simple?
Hi Please use stable postman version :
https://www.postman.com/downloads/
Canary builds usually for beta testing , the issue seems to be there and i have raised a bug:https://github.com/postmanlabs/postman-app-support/issues/9412
Update The issue is fixed now : https://github.com/postmanlabs/postman-app-support/issues/9412

Random permission/auhorization errors with Session.getActiveUser()

During the past week I have faced a nasty issue with my google apps script, which has been working just fine for several years already, with at least 500 users.
When I'm trying to get the login information of the current user this way:
var email_act = Session.getActiveUser().getEmail();
the server throws an exception:
Exception: You do not have permission to call Session.getActiveUser.
Required permissions: https://www.googleapis.com/auth/userinfo.email
at getUserInfo(UserFunctions:46:27)
In my case the effective user is different than active user, but I got the same error also when trying to call Session.getEffectiveUser().
This happens randomly, approx 30% of calls and so far my solution was simply to retry until it succeeds. Note that when I did the retries in the backend-code, it did not solve the problem, maybe because there's something wrong with the "session" itself. If it failed once, it failed also all the consequent calls. Therefore, I implemented the retry-loop in front-end code (assuming that each call to back-end is then considered as a new session) and that helped - after a few (worst case 5) retries it works. The Back-end has now a simple try-catch error handler and it returns status (-1) to FE in case of failure.
Any ideas what might be the root cause? My solution is way too uggly to live with...
Thanks in advance!
I just came across the same error today. For me, the Session.getActiveUser().getEmail() was in a scriplet on a dynamic webpage I create with a script using the function "include" that is defined in the code.gs like this:
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
It seems changing this to
function include(filename) {
return HtmlService.createTemplateFromFile(filename).evaluate().getContent();
}
has cleared things right up. I believe the error started occuring when I switched the code to the new V8 engine in GAS.
EDIT: oops, it worked the first time, but then failed after that. So I had to move the Session.getActiveUser().getEmail() inside code.gs
function getUserEmail() {
return Session.getActiveUser().getEmail()
}
and in the javascript on the webpage I had to use a callback :
google.script.run.withSuccessHandler(function (email) {
document.getElementById("yourIDhere").innerHTML = email;
}).getUserEmail();
Not very pretty at all, but it's working reliably now.

Cannot name get parameter 'pid' in google scripts get request

I want to pass a parameter to my google spreadsheet with a get request. The get parameter name is 'pid', which seems to make Google Sheets crash.
My example script just returns the get parameters to the client:
function doGet(e){
try {
return ContentService
.createTextOutput(JSON.stringify({"result":"your parameters", "parameters": e.parameter}))
.setMimeType(ContentService.MimeType.JSON);
} catch(ee){
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error message": ee}))
.setMimeType(ContentService.MimeType.JSON);
}
}
The following request works:
https://script.google.com/macros/s/<sheet-id-here>/exec?a=1
returns:
{"result":"your parameters","parameters":{"a":"1"}}
But simply changing the get parameter name returns an error:
https://script.google.com/macros/s/<sheet-id-here>/exec?pid=1
returns:
We're sorry, a server error occurred. Please wait a bit and try again.
Any idea what's going on here and how to fix this? Is this a bug? Is there a way to handle this on the server side (can't really change my client code)?
It seems Google has changed reserved parameters. As written in the documentation,
Warning: The following parameter names are reserved by the system and shouldn't be used in URL parameters or POST bodies:
c
sid
Using these parameters may result in an HTTP 405 response with the error message "Sorry, the file you have requested does not exist." If possible, update your script to use different parameter names.
It seems both c and sid parameters are valid now and pid parameter is reserved and throws
Sorry, unable to open the file at this time.
There doesn't seem to be anything that you can do server side.

Firebase "Error: Key creator was undefined. Cannot pass undefined in JSON. Use null instead."

I am using angularFire 0.8.2 for an app I am building. The app is based on thinkster.io's angular-firebase tutorial. The problem that I am facing is at the point where I have to create a custom user profile and and access the data stored in it. Especially, I am not able to make a post once I am logged in as a user.
I reviewed the error several times and kept getting the following error:
Error: Key creator was undefined. Cannot pass undefined in JSON. Use null instead.
The stack trace points to a service that was created to allow for post creations.
Here is the code:
var Post = {
all: posts,
create: function (post) {
return posts.$add(post);
},
get: function (postId) {
return $firebase(ref.child('posts').child(postId)).$asObject();
},
delete: function (post) {
return posts.$remove(post);
}
};
I looked at solutions provided for this same problem but they were not very helpful. I am only guessing the problem has something to do with the $add() method above. Can anyone help?
I know this was asked over a year ago however I thought I'd still add some help. My resolution was rather simple so maybe it will help future folks. The reason you see this message is because you have an undefined variable somewhere in your code/object you are attempting to $add. Firebase will reject the entire $add object if there are any undefined variables in your object's properties. Hope this helps.
In short there is really no error. When you followed the tutorial, the initial account you created had no username field and hence you did not give any. Now the updated code needs one and there is none. Just try creating a new account and post a new link. You won't see that error.

TypeError: Cannot call method "setSchema" of undefined

I am trying to connect a Google Spreadsheet with Google BigQuery for that I created a Google Apps Script but when I try to run it I get the following error:
Cannot call method "setSchema" of undefined.
The code calling setSchema is the following
var loadJob = BigQuery.newJob()
.setConfiguration(
BigQuery.newJobConfiguration()
.setLoad(
BigQuery.newJobConfigurationLoad()
.setSourceFormat("NEWLINE_DELIMITED_JSON")
.setSchema(sshema)
.setDestinationTable(json_table.getTableReference())
)
);
When I view the log for sshema I get a correct JSON like
{fields=[{name=first, type=STRING}, {name=last, type=STRING}]}
I am not sure how to solve the error, when I comment out the SetSchema line the error goes away...but obviously the script does not do what its suppose to.
Any tip in the right direction will be appreciated. Thanks!
UPDATE: I tried debugging the script and the line that is suppose to create the newJob() simply inserts the {} value into the loadJob variable. I am not sure why this is not working but at least it seems to be the problem.
This is a temporary bug, should be fixed in a week. You can track it at:
https://code.google.com/p/google-apps-script-issues/issues/detail?id=2906
In the meantime, you can bypass it by not chaining the sets(): https://stackoverflow.com/a/17420247/132438