User not getting prompted to allow app access to Google Drive - google-drive-api

To get a token, I am calling:
GoogleAuthUtil.getToken(context,account, "oauth2:" +"https://www.googleapis.com/auth/drive.appdata");
Which will always give me a token, so my code works, BUT I am expecting(at least the first time) to get a UserRecoverableAuthException so I can use that intent on the exception to prompt the user for action. The action in this case is granting my app access to that user's Google drive storage.
From the web site, I disconnect the app from the drive, run my app, files get written to my gdrive, and I see, from the website, that the app is connected to my drive.
Why is the user not getting prompted to allow access?

If user has already given permissions for you app for that scope, no UserRecoverableAuthException will be thrown.

I discovered in my case the Authorization dialog wasn't been showed because I added singleInstance to the activity in the AndroidManifest.xml
Removing from the AndroidManifest
android:launchMode = "singleInstance"
fixed this problem and a couple of other strange transition effects between activities.

The first time you connect your app to drive it asks for permission by itself when you send the account name.
The Exception you are expecting is only thrown if the user Disconnects the app.
Try disconnecting the app and then read/write to drive. It should throw this Exception.

Related

Drive API multi login iframe issue

I am using drive api in my app and it works well , but sometimes when multiple users are logged in and I try to open a file in the browser with the link fetched via drive api I see the error message "You need permission. Want in? Ask the owner for access, or switch to an account with permission. Learn more" .
Steps to reproduce :
login to google drive with one account.
login with a second account and use drive api.
when you try to open public files you get that error.
If you add access token in url it seems to resolve the issue but thats a security risk. If you add authuser param to url that also works, but I can't find a way to get current user's authuser param.
Any help is appreciated.

How to prevent suspended Google account to signup

I am integrating ASP.NET application using Google Drive API. For this after authentication we re uploading Files to Google drive. I am using Google client library to Call the APIs.
Everything is working as expected I am able to authenticate user successfully and able to upload the file successfully.
In one scenario when the user Google account is suspended then I am getting refresh token from Google but my upload method is failing and it is not uploading the file to Google drive.
I want to restrict the user on Signup screen itself, when account is suspended.
What parameter do I have to pass to achieve this please suggest?
Unfortunately this info is not easily available. You have two options :
Use the Directory API to see if the user is suspended. This requires additional OAuth permissions to be provided by an admin of the domain.
At login, try and perform a Drive API call to see if you get an error or not. If you get an error (with a couple of retried) and the error message matches the one you had for suspended users, then you can deny access to the user.

Google Drive scope drive.file not sufficient for copying app owned files to app user's Google Drive

Participating Components:
(all in the same project)
Android App
Web App
Service Account
The users have authorized the app on their Android devices with Cross Client Identity:
oauth2:server:client_id:[web_app_id].apps.googleusercontent.com scopes ...
Flow:
Several users request the creation of the same file through the Android app ( a file for every user is not desired, see "Known workaround" )
A service account then creates that file ( service account is owner )
Service account shares that file (by link and explicit with users)
User authorized drive service / or service account that impersonates a user tries to copy that file to the user's Google Drive ( User has to be the owner of that copy in the end)
Error:
This fails with scope drive.file ( and also drive.readonly ):
Error Message:
The authenticated user has not granted the app [project_id] write access to the file [file_id]
(btw: why write access is needed with copy()? giving users write access to the file does not change this error)
Known workaround:
It works with full drive scope
( but: my app does not need to see files it has not created - so i want to avoid it)
Same result can also be achieved by re-inserting the file instead of copying it
(this overhead is important for my app though, cause same file might be requested by multiple users)
An explicit interaction with a file from a UI Picker or so will propably not work as the file will have to be created after requesting it. also i can't think of a way how to do that without decreasing usability of the Android app.
Expected result:
www.googleapis.com/auth/drive.file: Per-file access to files created or opened by the app
It seems to me this should be enough.
As the file is created/owned/shared by my app's service account.
and copied by my app on behalf of the user.
www.googleapis.com/auth/drive.readonly Allows read-only access to file metadata and file content
At least this one should work as it should give read access to all files which should be enough to copy a "shared with user" file created by an "authorized by user" app.
Question:
the Web Application and the Service Account are in the same project.
Can the Web Application act like a Service Account on behalf of a user? if so - i don't know how. Would that make a difference anyway?
This seems like a Bug to me in this special use case, as the same result can be achieved with a workaround. At least scope drive.readonly should allow my app to copy app owned files to the user's drive.
Making a copy through the plain Service Account and then changing the owner of that copy to the User would be another workaround, but that fails too.
I must be missing something simple.
Please guide me.
Thank you.
I had the same problem and resolved it using the drive.metadata in combination with the drive.file scopes. Related question

Sending authorised GoogleApiClient to a service

I have an android application where Im uploading a file to Google Drive. First I load an activity and let a user make some choises, then I start an service that uploads the file in the background. As I understand I need to create the GoogleApiClient in an activity to be able to launch the authorization screens. How Im i supposed to get the then authorised GoogleApiClient to my background service?
You can instantiate the GoogleApiClient in the Activity once in order to ensure that the user has selected an account and authorized your app. Once they have done that once, they shouldn't need to do it again.
At that point you can create a new GoogleApiClient in your service and be fairly confident it will succeed. If it fails, you could always throw up a notification or some such indicating the user needs to take action.
That said, you shouldn't need a background service just to write a file. Since the actual upload will happen in the background already, all you need to do is write to the Contents in an AsyncTask.
I had the same problem...
I solve it by making part of my configuration activity the login to google (check if google play is installed, register and then connect). The activity asks for my google account and password.
My service then don't have problems with connect. I also find that I only have to supply my google login and password once. When I restart my app and I start the configuration activity, it connect to the drive SDK without asking my google login and password

appNotInstalled when the refresh token is missing?

Lately I've been noticing a strange behavior when trying to access Drive specific actions. The use case is as follows:
the user installs the Chrome Store application
the user launches the application, we get a refresh token for the email and the profile scopes
the user wants to export a document into Google Drive
error message 403: appNotInstalled is returned
If the user goes to Google Drive and opens a file from there using our application, they are redirected to a new authorization dialog that asks for the email, profile, drive scopes. After the user grants access, the initial export also works fine. My assumption is that the initial refresh token that we had was no longer valid, even though exchanging it for an access token worked and the refresh tokens don't expire.
Shouldn't we receive a more descriptive error message in this case that would suggest that we simply have to redirect the user to the authentication dialog instead of the Chrome Store listing?
The issue might be that you are using a different client id/secret than the one you registered for the Drive SDK.
A quick test would be to:
revoke all granted tokens for your application on your test account
visit your application from the New Tab Page, it should redirect you to the authorization page: copy the URL you generated (do not approve).
visit your application from Drive, it should redirect you to the authorization page: copy the URL (do not approve).
Make sure the 2 URLs are identical (they should be), especially look for similarities in the scope and client_id query parameters.