Opened 11 years ago

Closed 9 years ago

#4944 closed defect (fixed)

Google Fusion Tables SQL API Deprecated

Reported by: warmerdam Owned by: warmerdam
Priority: normal Milestone:
Component: OGR_SF Version: unspecified
Severity: normal Keywords: GFT Fusion Tables
Cc: Even Rouault, rburhum

Description

Per:

https://developers.google.com/fusiontables/docs/developers_guide

Important: The Fusion Tables SQL API has been officially deprecated as of June 26, 2012 and will be shut down after January 14, 2013. Please see the migration guide for instructions on how to move to the new API.

https://developers.google.com/fusiontables/docs/v1/migration_guide

Change History (3)

comment:1 by warmerdam, 11 years ago

Cc: rburhum added
Status: newassigned

Ragi and Even did an analysis and came up with the following information:

Investigated more and even posted a SO question. Things are more clear. Turns out the client authorization code becomes invalid after one [token+refresh token] exchange. So the key is to save the refresh token. Let me give you a summary:

Terminology:

  • appid: id used by google to identify the client doing the call. we generate it from the Google API console using a gmail/google apps account.
  • resource (public/private): a google fusion table.
  • token: string we need to send to access a private resource (not needed for public resources). Has expiration (typically 1hr - we know the expiration time when we request the token).
  • refresh token: string used to ask for a new token after our token has expired. Is valid constantly and only becomes "expired" when the user explicitly goes to the Google Accounts page and revokes access to the application.
  • authorization code: string we need to use to get a token and refresh token. *It is valid only once*. It is issued by Google after a client has authenticated using a browser in a Google login page.

Let me start by getting this out of the way: no matter what OAuth2 flow we pick, for the login portion, there will always be a browser with a Google login page. The OAuth2 flow allows us to pick how we grab that initial authorization code.

These are our options for the GFT driver flow:

1.- If the user wants to access a private resource using GFT, we will encounter a 403 if a *token* is invalid/missing.

2.- GFT attempts to use a *refresh token* to get a valid *token*.

  • If this process succeeds, we use the token and get the private resource.
  • If this process fails or we do not have a refresh token, we need to get one using 3)

3.- To get the authorization code, we need to direct the user to a URL we create. We can attempt to be smart about starting using a OS-specific call to start the browser ("open" in OSX, "start/explorer" in Windows, "xdg-open" in linux, etc). If the os specific call fails, we just print the url to the command prompt and tell them to go the url. From that point, to get the authorization code, we have several options from the authv2 flows

  • we pick one where the user will get the authorization code at the end, then they have to copy and paste it to us in the command prompt.
  • we start a webserver listening to an available local port (say 9091). Because of how we crafted the google authorization url, google will redirect to that url once the authorization happens and pass the authorization code.
  • we constantly poll a google-provided endpoint which will return the string IF the user has authorized the application.
  • the other flows require a web-facing application.

After 3) finishes, we have the required authorization code to get the first token and the refresh token( the first token is convenience since we could fetch it with the refresh token).

This leads to the question, where to store the refresh token.

With all this information, let me propose the following code changes:

Separating the OAuth hand shaking into a separate utility:

1.- One executable/python script that generates the refresh-token using one of the auth stupid flows

gdal_oauth2 "GFT" <refresh_token_output_location>

this will generate a file with a .txt extension that contains the token written to it. We pass GFT as a parameter so that we know what kind of permissions to ask for (i.e to google, for read/write fusion table)

2.- the GFT driver should take the token file location for the operations where private resource access is required.

So the upgrade to the new driver involves ditching client-login altogether and using the OAuthv2 flow described above. Feel free to ping me if there are any questions.

comment:2 by warmerdam, 11 years ago

As a preliminary step I have updated the driver in trunk to the v1 API (r25475), and also the tests (r25474).

Notable points:

  • ClientLogin (including the use of email and password) completely removed.
  • Updated to use v1 end api urls.
  • Updated to force use of "csv" results, and updated to honor slightly different responses to requests like deleting tables, updating and deleting features and so forth.
  • Registered for OAuth2 on behalf of GDAL using the "gdalautotest@…" account. Even and Frank have access. More can be added. Details (client id, client secret, client api key) are in top of ogrgftdatasource.cpp.
  • Added logic to exchange an OAuth2 authorization token for an access and refresh token. This can only be done once per authorization token. The authorization token is returned by the user visiting https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ffusiontables&state=%2Fprofile&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=265656308688.apps.googleusercontent.com
  • Subsequently the user can specify the refresh token indefinately using GFT_REFRESH_TOKEN configuration option or the refresh= clause in the connection string. (see ogr_gft.py test script for an example). Note that the refresh token lasts forever and effectively grants the holder the users full access writes to fusion tables as the user. Normally it should be kept secret! It can be revoked.

Still outstanding is a utility to make it easy to fire up the authorization request in a browser, capture the auth token and turn it into a refresh and/or auth token.

Also outstanding is finalization of user documentation.

comment:3 by Even Rouault, 9 years ago

Resolution: fixed
Status: assignedclosed

swig/python/scripts/gdal_auth.py exists and is documented in drv_gft.html. Closing

Note: See TracTickets for help on using tickets.