Search code examples
pythonoauthpicasa

How to make a long live Picasa token (or general Google oAuth 2.0 enabled services) using Python?


Got to say, I am not that clear how to use oAuth 2.0 with Picasa API version 2. From the Google doc itself, (cmiiw), I got the impression that Picasa API version 1 was deprecated, which means Python gdata for Picasa (that only support version 1), is simply useless.

Therefore, I develop my own class using the rudimentary Picasa documentation. But, I found that the token generated is very short lived: user got to reauthenticate him/herself again. Can we make user only reauthenticate one, and somehow the token got refreshed automatically if it's expired?

This is my oAuth class that I develop to solve this Picasa problem. Would love to have suggestion on how to fix this class to allow a long term lived token

class OAuth():
"""
Simplify oauth process
"""
def __init__(self, **kwargs):
    self.client_secret_file = kwargs.get('client_secret_file')
    self.token_location = os.path.join(kwargs.get('token_location'), kwargs.get('token_filename'))
    self.scope = kwargs.get('scope')
    self.credentials = None

def is_authenticated(self):
    storage = Storage(self.token_location)
    self.credentials = storage.get()
    authenticated = self.credentials is not None and not self.credentials.invalid
    Logger.debug('oAuth: authenticated = %s' % authenticated)
    return authenticated

def authenticate(self):
    if self.scope is None:
        Logger.error('oauth: please specify scope')
        return

    missing_message = '''
    WARNING: Please configure OAuth 2.0
    To make this code run you will need to populate the client_secrets.json file
    found at: %s
    with information from the Developers Console
    https://console.developers.google.com/
    For more information about the client_secrets.json file format, please visit:
    https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
    ''' % self.client_secret_file

    flow = flow_from_clientsecrets(self.client_secret_file,
                                   message=missing_message,
                                   scope=self.scope)

    # ca_certs_file = os.path.join('cacert.pem')
    flags = argparser.parse_args()
    storage = Storage(self.token_location)
    self.credentials = run_flow(flow, storage, flags)#, http=httplib2.Http(ca_certs=ca_certs_file))

EDITED: I add my solution here.

def get_album_list(self):
    if self._album_list is not None:
        return self._album_list

    http = httplib2.Http(ca_certs=os.environ['REQUESTS_CA_BUNDLE'])
    http = self.oauth.credentials.authorize(http)
    response, album_list = http.request(Picasa.PHOTOS_URL, 'GET')

    if response['status'] == '403':
        self.oauth.credentials.refresh(http)
        response, album_list = http.request(Picasa.PHOTOS_URL, 'GET')
    album_list = json.load(StringIO(album_list))

    self._album_list = {}
    for e in album_list['feed']['entry']:
        album_id = unicode(e['id']['$t'].split('/')[9]).split('?')[0]
        self._album_list[e['title']['$t']] = album_id
    return self._album_list

Solution

  • There are two types of tokens: access token and refresh token. Your application should receive both when a user grants you an access for the first time.

    {
      "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in":3920,
      "token_type":"Bearer",
      "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
    }
    

    It is important to save refresh token for further use. When the first access token expired you have to use the refresh token to obtain a new one.

    https://developers.google.com/accounts/docs/OAuth2WebServer#refresh

    Also consider using https://github.com/google/oauth2client