Reducing Google Drive scope: a simple proposal

Hey all,

Google is changing the policy around how apps can access Drive data soon (see Enhancing security controls for Google Drive third-party apps) and I was looking into whether this will affect Duplicacy.

Based on what I understand, it will. Specifically, the issue is that the scope is becoming restricted (see the full list of OAuth 2.0 scopes here) and this scope is used by tokens generated by the endpoint.

However, I believe there’s no need for Duplicacy to use this scope. The much less dangerous scope is more appropriate: this would only allow Duplicacy access to files and folders that it creates. In fact, there are no changes needed to Duplicacy’s codebase, the only change needed is how the token is created.

My proposal therefore is to retire the endpoint and instead replace it with a simple CLI that allows the user to generate a token locally and uses the scope. The way I’ve done this was using the code from Go Quickstart for Drive, so this CLI could be based on that. When the user first tries to use Drive storage without a token, they are asked to visit a link to authorize the app and copy-paste an auth code, after which a valid token is generated.

Hope this proposal is helpful, thoughts welcome!

1 Like

I can modify to use the drive.file scope, but the problem is that Duplicacy CLI doesn’t automatically create the storage directory during initialization if the directory doesn’t exist. So this scope change requires code changes to Duplicacy CLI, and maybe the web GUI too.

Duplicacy CLI doesn’t automatically create the storage directory during initialization

Might be a recent change, but it seems it does: when the storage is initialized, getIDFromPath is called with createDirectories set to true.

I’d still love it if the CLI could generate the token, just as a good security practice, but changing is probably a good start.

I forgot about that change. So probably no code change is needed for the CLI, but the web GUI definitely needs some work (like adding a button to create a new directory).

I don’t want to create another CLI executable just for this purpose. Maybe it is possible to create a static html page with some javascript instead of a CLI. This page can be hosted on dropbox for example, and the user can create their own Google Drive app, enter the client id and secret on this static page, and then authorize the app to access Google Drive. After the authentication, Google Drive will send the token to another static html page (provided as the Authorized redirect URI when creating the Google Drive app) which will decode the parameters passed in the URL into a downloadable token file).

Come to think of it, this can simply be added to the existing CLI: if no token is provided, instead of asking for a path, Duplicacy can trigger the OAuth 2 flow and generate a token on its own.

Maybe it is possible to create a static html page with some javascript instead of a CLI.

You don’t need an HTML page at all. Google has a special OAuth 2.0 flow for installed apps that works like this:

  1. urn:ietf:wg:oauth:2.0:oob is used as a special redirect URL to trigger the flow.
  2. When the user finishes the OAuth 2.0 flow on, instead of being redirected, they are provided the authorization code directly to copy-paste.
  3. The user copies this code to the CLI which reads it via standard input (e.g. fmt.Scan).
  4. The CLI exchanges the authorization code for an access token and refresh token.

The Go Quickstart for Google Drive has code that does exactly this and is very simple, try it out. That page also has an Enable the Drive API button that somehow magically creates a Cloud Console project and generates a client ID and secret automatically in one click.

Another option is to use a localhost URL as the redirect. In this case, Duplicacy would start a local HTTP server and Google would redirect to it (and pass the authorization code) when the user completes the OAuth 2.0 flow. This is a bit more complicated, but requires no copy-paste from the user. It’s probably an overkill for the CLI, but may be useful for the GUI if you want to make it more user-friendly.