I have an internal app (not a published one, only used within our Google Workspace domain) which is a command line tool to update the contents of some Google Sheets. It currently uses the https://www.googleapis.com/auth/drive scope and works fine.
I want to minimize the privileges of the authorization token that this app caches, and by reading the documentation it seems that I should be able to use the https://www.googleapis.com/auth/drive.readonly scope to find the file I want, and also https://www.googleapis.com/auth/drive.file to grant write access to only a specific file.
With the reduced scopes, I am not surprised to get an error like:
appNotAuthorizedToFile: The user has not granted the app 566375348811 write access to the file 1UsItGhBHwRaodHbv5g1LCrSESUZBkskDvKDkbGjREjI
The only relevant documentation talks about integrating apps with Google Drive and using the Drive Picker UI which I expect does this authorization behind the scenes. Since this is an internal command line tool, I really don't want to go that route.
Hence the question:
How do I open a file in a command line application using the https://www.googleapis.com/auth/drive.file scope?
I'm OK even if I need to set some magic metadata on the file to make it accessible.
Update
As I got a couple of responses saying that when using drive.file it is not possible to access files which are not created by the application, I am putting some supporting documentation here to show why I think it is possible:
The API-specific auth info is the first document on the Google Drive API page, and it specifically mentions:
So, when possible, use non-sensitive scopes as they narrow access to
specific functionality needed by an app. In most cases, providing
narrow access means using the
https://www.googleapis.com/auth/drive.file per-file access scope.
Further down the page it mentions:
This scope enables users to select the specific files from Google
Drive, and through the Google Picker, that they want to allow your app
to access.
I understand this to mean that it is possible to open files which were not created by the app, even when using drive.file.
My problem is that the document goes on to explain:
Many apps work with per-file access without any changes. If you are
currently using your own file picker, we recommend switching to the
Google Picker which fully supports the drive.file scope.
Well, since I am using a command line app, I cannot use the Google Picker, so I am asking how to implement my own. I do understand that the picker itself needs to have access to all the files (hence the need for a drive.readonly scope), but to actually be able to write the files, it needs the elevated permission of drive or the more restrictive per-file access of drive.file.
If I simulate an authorization request for drive.file I get a prompt which explains that authorizing the request will grant my app to:
See, edit, create, and delete only the specific Google Drive files you use with this app ℹ️
Clicking on the information icon I get a more verbose explanation which reads like it support opening any file I authorize:
This app wants permission to create new files or change existing files
that you open with this app. Once authorized, the app can:
See these files
Upload and download these files
Delete these files
See the names and emails of people you share these files with
Share and stop sharing these files with others
Organize these files
There may be private information in your Google Drive, like financial
records, medical reports, photos or tax info.
There are also other examples of applications like ZIP Extractor or diagrams.net or Photo Editor which use the drive.file scope (based on the authorization prompt), and which I can use to open and edit files that were not created by them.
I am posting this as an answer, to demonstrate an ugly "workaround" for the issue.
TL;DR: Use a web based frontend to authorize access to files. Once the app is authorized, the command line app inherits the permissions.
More step by step instructions, assuming we already have a working command line project:
Go to https://myaccount.google.com/permissions and revoke all access I have granted to my app.
Follow the instructions at the Drive Picker API to update my current GCP project.
Create an API key. OK to be unrestricted, but I restricted it to https://localhost:9843
Create a new OAuth 2.0 client ID of a "Web application" type (my current one is "Desktop" type and that would not work). Authorize https://localhost:9843 as a JavaScript origin.
Copy the helloworld.html example at the bottom of the Drive Picker API guide which is also on GitHub with the following modifications:
Set developerKey to the API key created above
Set clientId to the new OAuth 2.0 client ID created abovce
Set appId to the numeric project ID of my GCP project
Add 'include_granted_scopes': true to the call to window.gapi.auth.authorize
Update createPicker to make it easier to find the files I want. E.g., set the mime type filter to application/vnd.google-apps.spreadsheet.
Host the example in a browser with ruby -rwebrick/https -e 'WEBrick::HTTPServer.new(:Port => 9843, :DocumentRoot => ".", :SSLEnable => true, :SSLCertName => "CN=localhost", :SSLCertComment => "Autogenerated" ).start'
Now, if my command line app fails to edit a file, I can use https://localhost:9843/helloworld.html to grant access to the file, and my command line app can then edit that file.
If you check the docs for the scope you will find it says.
https://www.googleapis.com/auth/drive.file View and manage Google Drive files and folders that you have opened or created with this app
This gives your app access to files that the app itself created or has previously opened.
You should also know that there is no way to limit authorization to a single file. Authorization is all or not thing.
How do I open a file in a command line application using the https://www.googleapis.com/auth/drive.file scope?
You make sure that the file was created by the app itself. using files.create. If the file was created by any other app the you cant access it using the drive.file scope
There is one note though if you have https://www.googleapis.com/auth/drive.read-only scope and you open that file to read it. the line where it says opened or created with this app implies to me that once you have opended it for read in this app that you would then be able to use it with https://www.googleapis.com/auth/drive.file but its not something I have tried.
Another thing is im not sure what you mean by open the google drive api is a file storage api its not going to let you see the contents of the file your going to have to download it and open it locally. Have you considered going though the Google sheets api if you want to read and write to it programmatically?
Is it possible to share google drive access of other email address using oAuth2 and javascript client API?
If I have both of other's emailaddress and password?
If using Service account?
I just want to create an app that will allow other Google Signed In users to see and manage my files and directories.
Let me know what is your idea, best practices, steps on this. Thanks
Ok so we are clearn here person one is the person who would like to share something on their drive with person two.
Your application uses oauth2 to authenticate person one. Then you use the Permissions method to insert permissions for Person two into what ever file or folder you wish to share with them. Its person one who has to do this.
Notes:
Service accounts dont work with JavaScript client side you would need to use a server sided language. Service accounts are a dummy user you would be granting the service account access and not person two.
You cant share the whole drive you cant share the root folder. You could write a script that shares everything under root. But someone else cant write to your root folder.
I am writing a slack app having a bot user also. I am currently working on a workflow where if a user is sharing a file with the bot or uploading to a channel and then sharing a file with the bot I want to download that file. Till now what I have done is if a user is sharing a file then I am listening to file_share event and whenever I got the event then I am getting the file object with the event also having a field named "url_private" which helps me to download the file. But now the issue is to download the file I have request that URL along with user token or api token(Token that starts with xoxp-) but for a team that token is the token of the member who has installed the app in the workspace but for all other members I don't have the token so I am not able to download the file. So I want to know if I can get the token for all other members to download the file or my understanding is incorrect and I am not obliged to download the file that belongs to the user. Please help.
No, you do not need to gather access tokens from all you users.
Once a file has been shared in a channel with your bot you can download it using the bot's token as follows:
Make a GET call to the URL from the url_private property
Provide the bot's access token as authorization in the header. The syntax is:
Authorization: Bearer A_VALID_TOKEN
See here for reference and additional infos.
I want to develop an application that uses the Picasa Google API for uploading images to my own account. I've already created the Service Account from the API Console and have created the code to upload the image (which works correctly given a valid access_token obtained from the OAuth2 playground).
However, when trying to obtain an access_token with the Google-api php library, this one doesn't seem to be associated to my own username (obviously, no consent screen), which throws me a 404 Not found error message when trying to access data from my personal account.
From what I've read over at https://developers.google.com/api-client-library/php/auth/service-accounts I could create an apps account to setup permissions for a whole domain. Is this, however, necessary given that I only want to access information from my own account? (the same I used to register the application in the API console). Couldn't this be done beforehand using API panel?
A service account is not you and does not by default have access to any data. Think of a service account as a dummy user. If you take the service account email address and add it as a user on a folder in your google drive it will have access to that folder on google drive. If you take the service account email address and give it access to one of your calendars on Google Calendar it will have access to the calendar.
If you set the album public I suspect it will then have access to the album. I did some Googleing and I cant see how you can add another users email address to an album on picasa.
I suggest you try using Oauth2.
Our platform is using a Google Service Account to create folders on Google Drive and share the folders with some of our end users. Think of it as a replacement for the traditional hot folders on an ftp site.
The problems may seem minor but when the end-user sees our shared folder the owner appears as the service account email address which is pretty ugly and I'm assuming not meant for end-user viewing: "178235058172-hi96h0con2ipmnli26tn17bdodb5ba4c#developer.gserviceaccount.com". It's also the sender email address when the user receives the "I've shared an item with you" email when we share the folder with them.
Is there any way to have the email address be the name of our service? or a way to change the name of the owner of the shared folder?
It is not possible to change the name of the service account. Nor is it possible to give it a name.
You could crate a dummy gmail account for the company. grant it owner. Give the service account write access to it.
However if the service account shares the folder with someone its still going to show as the service account has shared the item with them.
Only real work around I can think of would be to use Oauth2, authenticate the code once so you have a refresh token. Then use the refresh token to gain access faking a service account. Its not truly a service account and if something happens to the refresh token you are going to have to reauthentcate.