Google Drive authentication issues - google-drive-api

I'm having an issue using Google Drive using Ruby.
I can create an OAuth2 client and start making authenticated calls.
I have to query the Google Documents List first in order to fetch a list of files, once I have the file IDs I try to query the Google Drive API like this:
GET https://www.googleapis.com/drive/v1/files/0B9N873iFyYR7MkRfeTAxxxxxxx?access_token=ya29.AHES6ZRckKZ2jZfC6risUtH9ZZxxxxxxxxx
However I'm getting this:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "appNotInstalled",
"message": "The authenticated user has not installed the app with client id xxxxx.apps.googleusercontent.com"
}
],
"code": 403,
"message": "The authenticated user has not installed the app with client id xxxxx.apps.googleusercontent.com"
}
}
This client id refers to an application I created via Google API Dashboard, not the Chrome Web Store.
Anyway I tried to setup a hosted Chrome Web App, configured (and paid) everything to allow a list of test users, but still I get the same error message although the app is installed correctly from the market (not local copy).
With the same client and credentials I'm able to call https://docs.google.com/feeds/ endpoints but not drive ones.
My scopes are rather complete: 'https://docs.google.com/feeds/,https://docs.googleusercontent.com/,https://spreadsheets.google.com/feeds/,http://gdata.youtube.com,plus.me,drive.file,userinfo.email,userinfo.profile'(don't look at the format, it gets fixed automatically afterwards) and they works well.
I'm not using the Drive UI, I just want to use server-side APIs. Thanks for any hints.

Have you set the "api_console_project_id" : "xxxxxxxxxxxxx" argument in your manifest ?
An example is provided here: manifest.json

Related

Google Drive API failing - Unusual traffic from your computer network

The Google Drive API GET query started to fail (we are using this api in one of our client service):
https://www.googleapis.com/drive/v3/files/1ke4Yoxxxxxxxxxxxxxx?alt=media&access_token=ya29.ImG9BwT.....
We're sorry...
... but your computer or network may be sending automated queries. To protect our users, we can't process your request right now.
See Google Help for more information...
"Unusual traffic from your computer network"
Everything was ok till today.
Just made a couple of tests with curl:
HTTP GET with access_token inside HTTP header:
curl -H "Authorization: Bearer ya29._valid_access_token" https://www.googleapis.com/drive/v3/files/1r5BT2WPrulQ6FyhT8RcqV51TVOThEmhK?alt=media
Result: success, file downloaded.
HTTP GET with access_token as a part of HTTP request:
curl https://www.googleapis.com/drive/v3/files/1r5BT2WPrulQ6FyhT8RcqV51TVOThEmhK?alt=media&access_token=ya29._valid_access_token
Result: error
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
}
],
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
}
Note that the Google API project approved by Google and has a Production state!!!
Hi Google team, any ideas why it is happening?
Thank you
Posting this just for documentation purposes. As per the reference provided by Tanaike, since January 1, 2020:
download calls to files.get, revisions.get and files.export endpoints which authenticate using the access token in the query parameter will no longer be supported.
Only requests that download media content (alt=media) are affected by this change.
The access token should be provided in the HTTP header, like Authorization: Bearer oauth2-token or, if that's not possible, follow the workarounds provided in the referenced documentation:
For file downloads, redirect to the webContentLink which will instruct the browser to download the content. If the application wants to display the file to the user, they can simply redirect to the alternateLink in v2 or webViewLink in v3.
For file exports, redirect to the export link in exportLinks with the desired mime type which will instruct the browser to download the content.
Reference:
Changes in authorization to Google Drive API
Authorization via HTTP header
Posting an addition to the documentation of iamblichus specific for application data in Google Drive.
My App uses the Google Drive API in the backend to store the documents of my users on their own Drive. Importantly, I store the data in an application data folder such that the users can't accidently delete the data.
To let the users retreive their documents I used to redirected the user to the
downloadUrl: https://www.googleapis.com/drive/v2/files/id?alt=media&source=downloadUrl&access_token=ya29.** where I added alt=media and access_token to the query. This worked fine till January 1, 2020. As confirmed above. However, now the request fails with the message:
We're sorry... ... but your computer or network may be sending
automated queries. To protect our users, we can't process your request
right now.
GET request downloadUrl failing
In my efforts to find a solution to this problem I've tried the workarrounds provided by Google but they are in my experience not working for documents in an application data folder.
I tried the webContentLink with the access_token query in v2 but it fails with an 401 Unauthorized error.
The alternateLink in v2 and the webViewLink in v3 fail with the error:
The desired file does not exist.
I can't use the exportLinks because that's only for Google Documents.
The solution I found was to first download the file to the server using the Google Drive PHP SDK and then serve it to my users using a Content-Dispostion header. Such as described here. It is a lot less elegant in my opinion because the end users doesn't download the document directly from the Google Drive API but it works.
It's a shame that Google didn't update their documentation nor notified their users..

Permission Denied by Google Cloud Datastore API when accessing from Google Apps script

We have created a Google Apps script, that is supposed to look-up in the Google Cloud Datastore for certain record keys, and if they do not exist, begin a transaction and commit these records.
The script did work successfully with the service-account and the datastoreID of the Google Cloud project MYAPP-TEST, but when we changed the settings to the service-account and datastoreID of the actual Google Cloud project MYAPP-LIVE, only the lookup request works successfully with the expected response, but the beginTransaction request always results in an error:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "PERMISSION_DENIED",
"message": "Unauthorized."
}
],
"code": 403,
"message": "Unauthorized."
}
}
My question is, why does the one request succeed and the other request fails for one datastore (MYAPP-LIVE), while everything (and more) works flawless with the other datastore (MYAPP-TEST). We tried to replicate the settings for both datastores, but maybe we are missing something. So, these is what we have done and the setup. Maybe you have an idea what would explain the different behavior of the script.
MYAPP-LIVE has been created years ago in the old App Engine admin pages and uses custom domains, the same as we have in our Google Apps for Work domain. MYAPP-TEST was created a few weeks ago in the new Google Cloud console. Both have a datastore. The way how both projects have been created are different and no custom domain is used for MYAPP-TEST, that should be the only differences I can think of.
The script uses Google Cloud Datastore API 1beta2.
The lookup request is sent to:
"https://www.googleapis.com/datastore/v1beta2/datasets/"+datasetId+"/lookup?fields=deferred%2Fpath%2Fname%2Cfound"
with some keys in payload, which I think is irrelevant here.
The beginTransaction request is sent to:
"https://www.googleapis.com/datastore/v1beta2/datasets/"+datasetId+"/beginTransaction"
with {payload:{"isolationLevel": "SNAPSHOT"}} stringified.
Both requests also use these options:
var options = {
method: "POST",
contentType : "application/json" ,
muteHttpExceptions : true,
headers: {
"authorization": "Bearer " + accessToken,
}
}
Both requests use the same accessToken, which is retrieved through Google Samples Apps Script oAuth2 for authentication.
In both projects, MYAPP-LIVE and MYAPP-TEST, we had created service-accounts with the editor-role and with the option Domain-wide Delegation turned on. This was done in Google Cloud Developer console under Home > Permissions
The downloaded P12 JSON is used in the script like this:
var keyObj = {
"type": "service_account",
"project_id": "MYAPP-TEST",
"private_key_id": "149b.............3536d",
"private_key": "-----BEGIN PRIVATE KEY-----\n40c4......be321==\n-----END PRIVATE KEY-----\n",
"client_email": "srvacct4gas#myapp-test.iam.gserviceaccount.com",
"client_id": "1033..........6420",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/srvacct4gas%40myapp-test.iam.gserviceaccount.com"
};
The P12 JSON was replaced with that of the service account in MYAPP-LIVE.
In Google Cloud Developer console under Home > API, we also turned on Google Cloud Datastore API and (not sure if really needed) Google Drive API.
In Google Apps for Work, Admin page Manage API client access, we also added the service-account of MYAPP-LIVE, the same way we did earlier with MYAPP-TEST, that is with the Client ID copied from the service account and these scopes:
https://www.googleapis.com/auth/datastore
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/userinfo.email
In addition, we changed the Google Apps script's Developer Console project number of MYAPP-TEST to the number of MYAPP-LIVE (in the script menu: Resources > Developers Console Project ...
Finally, I also have reversed the sequence of the requests, first the beginTransaction, but it fails again with the same error.

Set up Google Calendar V3 API Push notification via my Google Apps script

I want to use Google CAL API v3 to watch multiple calendars and thus to update all those events from those calendars to a Master Calendar, so I need to use WATCH/PUSH notification in order that whenever there is a new event in those cal’s, those events shd be automatically be pushed/created in my master calendar.
But, I am facing the following issue :Under APIs Explorer. Most of the services return 200 OK, except the Watch request not working.
Services > Calendar API v3 > calendar.events.watch
i got the below request and response
Request
POST https://www.googleapis.com/calendar/v3/calendars/mailid%40domain.com/events/watch?key={YOUR_API_KEY}
{
}
Response
400 OK
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "entity.resource"
}
],
"code": 400,
"message": "entity.resource"
}
}
And then i followed as per the below google documentation
https://developers.google.com/google-apps/calendar/v3/push
Registering Your domain:
Step 1: Verify that you own the domain
Step 2: Register your domain
I verified my domain/notifications in google webmaster tools.
My verified domain look like this:
http://my-domain.com/notifications
And have added my domain name in the webhooks under the PUSH in Google Developer Console, as explained in the doc.
Is there anything i am missing here, plz is there an issue in SSL certificate fr my domain, how can i atleast test in the API explorer, so that i get a return code 200 OK. After that, I need to implement this push/WATCH via Google Apps Script.
Is there any documentation for apps script to use push notification.
Any hint, tip will help me, I am tired with this for the past 1 week in trial and error method.
In the request that you posted the body is empty. In the documentation there is an example where you need to provide the calendar ID, the web_hook and other information:
{
"id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
"type": "web_hook",
"address": "https://example.com/notifications", // Your receiving URL.
...
"token": "target=myApp-myCalendarChannelDest", // (Optional) Your channel token.
"expiration": 1426325213000 // (Optional) Your requested channel expiration time.
}
Add this information when creating the push notification.
For using apps script you can use URLfetch service with the method "fetch()" then you would need to provide the parameters mentions and make the call as a POST.
Hope this helps.
UPDATE: I will write here to have more space.
Push notifications work in this way.
-You create a push notification with the id, the resource you want to watch, the address where you want to receive the notification and the optional parameters.
-if successful, the server will watch that resource and will send a notification to the address mentioned in the request describing the changes when a change is made to the resource.
-The server needs to know that you received the notification, so from the address mentioned in #1, you need to tell the server that you received the notification returning a HTTP 200 response. (for this you need an app that is listening to the notifications and sending the responses)
for your questions
1.- As the server will make a HTTP request to a url (your web_hook address) Google requires it to be secure, that's why it is required to be HTTPS.
2.- Yes, without that url you won't be able to receive the notification.
3.- Google also needs to verify that the url you provided is actually yours, so you will need to provide the url, then Google will provide you a file, you have to make this file available in that url, then Google will call the url an will retrieve that file. Then you can prove that the URL is yours. I'm not sure if this step can be done with apps script. You can actually deploy a script as web app but i'm not sure if you can use it for this purpose.(here you can find more info and different ways to verify the url)
4.- That's created by yourself. In the documentation is pointed out the recommendations for it.
I hope this clarifies your questions.
You can check here how push notifications work, this example is for Drive but the concept is the same.

Google maps APIs for Business returning error code 403 reason accessNotConfigured

I am using Google Maps APIs for business to get location against Cell IDs and MAC addresses of WiFi access point.
That code was working fine on beta server. Now as I moved to production server, I am getting following response
{ "error": { "errors": [ { "domain": "usageLimits", "reason": "accessNotConfigured", "message": "Access Not Configured. Please use Google Developers Console to activate the API for your project." } ], "code": 403, "message": "Access Not Configured. Please use Google Developers Console to activate the API for your project." } }
In console, Beta server IP was added in allowed IPs. I have added production server IP as well. Still getting above response.
Do I need to generate new key after change in allowed IPs or any other change?
The message is self-explaining activate the API for your project
Go to the console, select the desired project(when you have multiple projects), go to APIs & auth ->API's and activate the service Google Maps Geolocation API

Google Drive Error: Registered app required, either through authentication token or key param

Suddenly today requests from my service attempting to insert a file into Google drive via the Drive API started to receive a 400 error. The error indicates that a registered app is required, full error below. An application was already registered in my Google Cloud console, however the applications name did not match the application name that was used by my service. I renamed the services application name, however the error continues.
400 Bad Request
{
"code": 400,
"errors": [
{
"domain": "global",
"message": "Registered app required, either through authentication token or key param.",
"reason": "required"
}
],
"message": "Registered app required, either through authentication token or key param."
}
Is there something else that needs to be setup, or could this be a delay in the renaming of the service?
EDIT: I'm able to list, update and download files however I cannot insert.
This same issue just started to happen to us today - and we made no changes. I (think I) submitted a bug report to Google about this. Will keep digging..
UPDATE: I created a new project with private key and client ID/email and I get the same error with this new project as well. This appears to be some bug with Google Drive API service.
It happens today on my app too. I guess their service is having problem today