1

Can anyone provide sample code that would be a working replacement for the code that used the now defunct gdata.docs.client API:

import gdata.docs, gdata.docs.client, gdata
pw = file('pw','r').read()
client = gdata.docs.client.DocsClient()
client.ClientLogin('username@domain.org',pw,None)

Until yesterday, that code worked, but google has finally axed the depreceated ClientLogin API (https://developers.google.com/identity/protocols/AuthForInstalledApps).

In reading over the documentation for the OAuth 2.0 library, it looks like the process is supposed to involve user interaction to finish the authentication process, but I need a script to run in a cronjob on a regular basis without user involvement (we update various parts of our google site using a script on a cronjob).

Current Answer:

Hard-coding authentication for the docs API was possible, but that API is also discontinued, so here's the way to do it for the new, preferred DRIVE API.

credentials = OAuth2WebServerFlow(
    client_id = "CLIENT ID",
    client_secret = "CLIENT SECRET",
    scope = 'https://www.googleapis.com/auth/drive',
    user_agent = "HTTP",
    access_token = "ACCESS TOKEN",
    refresh_token = "REFRESH TOKEN",
    )

# Create an httplib2.Http object and authorize it with our credentials                                                                            
http = httplib2.Http()
# Now it gets ugly
# The authorize method below changes the "request" method of http_client
# Not at all sure why I had to fake this to make it work, but I did -- 
# I believe this must get set somewhere in the normal gdrive flow which
# we're circumventing with this method. You can see the code that
# requires this fake client here: 
# https://code.google.com/p/gdata-python client/source/browse/src/gdata/gauth.py
# at ~line 1324
Class FakeClient:   
    request = 'Fake'
http.http_client = FakeClient()
http = credentials.authorize(http)


# Create an httplib2.Http object and authorize it with our credentials                                                                            
http = httplib2.Http()
Class FakeClient:
    request = 'Fake'
http.http_client = FakeClient()
http = credentials.authorize(http)

In order to get those credentials, you can use the standard OAuth method described in the google documentation and then just dig into the variables to find all the right information. Here's some code I wrote myself to print it all out:

if NEED_NEW_CREDENTIALS:                                                                                                                          
    CLIENT_ID = 'ID'                                                                                                                              
    CLIENT_SECRET = 'SECRET'                                                                                                                      
    OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive'                                                                                         
    REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'                                                                                                    
    flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE,                                                                             
                               redirect_uri=REDIRECT_URI)                                                                                         
    authorize_url = flow.step1_get_authorize_url()                                                                                                
    print 'go to the following link in your browser: ' + authorize_url                                                                            
    code = raw_input('Enter verification code: ').strip()                                                                                         
    credentials = flow.step2_exchange(code)                                                                                                       
    print 'Hey buddy -- you better hardcode these new credentials in.'                                                                            
    print 'client_id = "%s"'%credentials.client_id                                                                                                
    print 'client_secret = "%s"'%credentials.client_secret                                                                                        
    print 'scope = "%s"'%OAUTH_SCOPE                                                                                                              
    print 'user_agent = "%s"'%credentials.user_agent                                                                                              
    print 'access_token = "%s"'%credentials.token_response['access_token']                                                                        
    print 'refresh_token = "%s"'%credentials.token_response['refresh_token']
Tom Hinkle
  • 61
  • 7
  • possible duplicate of [How do I authorize a gdata client without using the gdata oauth2 workflow?](http://stackoverflow.com/questions/14742382/how-do-i-authorize-a-gdata-client-without-using-the-gdata-oauth2-workflow) – mwhite May 27 '15 at 22:40
  • It seems you can get an oauth token manually and then hard-code it into your application, assuming you don't need to do this for arbitrary users. – mwhite May 27 '15 at 22:40
  • yes it must involve user interaction the first time only (when you get the refresh token). impossible to pass directly username and password (which is great. that old method was insecure) – Zig Mandel May 27 '15 at 23:13
  • Ok -- updated post to include latest solution. Note that the docs API, like the old authentication method, is now dead, so I've updated this to work with the drive API. – Tom Hinkle May 28 '15 at 01:50

1 Answers1

1

Ok, I found a better solution in the PyDrive library, which already wraps all of this nicely up for you:

http://pythonhosted.org/PyDrive/

If you set PyDrive to store credentials, it will only make you go through the browser once, then remember the credentials automatically.

You'll need to set up a settings.yaml file that looks like this to work with it:

save_credentials: true
save_credentials_backend: file
save_credentials_file: credentials.txt
client_config_file: client_secrets.json

Once you've done that, and installed your secret in client_secrets.json, the login process is as simple as:

from pydrive.auth import GoogleAuth
gauth = GoogleAuth()
gauth.LocalWebserverAuth()

Then you're working with the PyDrive API, which is pretty friendly to use and well documented here: http://pythonhosted.org/PyDrive/oauth.html#customizing-authentication-with-settings-yaml

Tom Hinkle
  • 61
  • 7