I am using googles official oauth2client.client to access the google plus api. I have a refresh token (that does not expire) stored in a database, and need to recreate the
I solved this quite easily (you certainly miss this documentation). This is a snippet of my code that tries to use Picasa API to get all of album from active user:
http = httplib2.Http(ca_certs=os.environ['REQUESTS_CA_BUNDLE'])
try:
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))
except Exception as ex:
Logger.debug('Picasa: error %s' % ex)
return {}
Use the refresh
method coming from oauth2client.client.OAuth2Credentials. I think it's even okay to use if response['status'] != '200'
. Got to check that!
You could store the entire credentials rather than only the refresh token:
json = credentials.to_json()
credentials = Credentials.new_from_json(json)
Look at the Storage object which does it this way.
If you are using the 2018 Youtube Python Quickstart demo app using google-auth, you can't use oauth2client's storage.
So here is the correct way of storing the credentials
Here is a partially working solution for google-auth, missing the correct handling of the case where the token expires:
import os
import json
import os.path
import google.oauth2.credentials
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google_auth_oauthlib.flow import InstalledAppFlow
CLIENT_SECRETS_FILE = "client_secret.json"
SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'
def get_authenticated_service():
if os.path.isfile("credentials.json"):
with open("credentials.json", 'r') as f:
creds_data = json.load(f)
creds = Credentials(creds_data['token'])
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
creds = flow.run_console()
creds_data = {
'token': creds.token,
'refresh_token': creds.refresh_token,
'token_uri': creds.token_uri,
'client_id': creds.client_id,
'client_secret': creds.client_secret,
'scopes': creds.scopes
}
print(creds_data)
with open("credentials.json", 'w') as outfile:
json.dump(creds_data, outfile)
return build(API_SERVICE_NAME, API_VERSION, credentials = creds)
def channels_list_by_username(service, **kwargs):
results = service.channels().list(**kwargs).execute()
print('This channel\'s ID is %s. Its title is %s, and it has %s views.' %
(results['items'][0]['id'],
results['items'][0]['snippet']['title'],
results['items'][0]['statistics']['viewCount']))
if __name__ == '__main__':
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
service = get_authenticated_service()
channels_list_by_username(service, part='snippet,contentDetails,statistics', forUsername='GoogleDevelopers')
I use: oauth2client.client.GoogleCredentials
cred = oauth2client.client.GoogleCredentials(access_token,client_id,client_secret,
refresh_token,expires_at,"https://accounts.google.com/o/oauth2/token",some_user_agent)
http = cred.authorize(httplib2.Http())
cred.refresh(http)
self.gmail_service = discovery.build('gmail', 'v1', credentials=cred)
If you already have a Credentials
object then you can refresh it like so:
if refresh:
import google_auth_httplib2
# credentials instanceof google.oauth2.credentials.Credentials
credentials.refresh(google_auth_httplib2.Request(httplib2.Http()))
I had created the Credentials
object from an old token JSON file like so:
credentials = google.oauth2.credentials.Credentials(
token=token_json['access_token'],
refresh_token=token_json['refresh_token'],
id_token=token_json['id_token'],
token_uri=token_json['token_uri'],
client_id=token_json['client_id'],
client_secret=token_json['client_secret'],
scopes=token_json['scopes'])
In this way I was able to adapt some old oauth2client
code.
In case anyone is looking for the answer for how use a refresh token with google_auth_oauthlib
, the following works for me:
flow.oauth2session.refresh_token(flow.client_config['token_uri'],
refresh_token=refresh_token,
client_id=<MY_CLIENT_ID>,
client_secret=flow.client_config['client_secret'])
creds = google_auth_oauthlib.helpers.credentials_from_session(
flow.oauth2session, flow.client_config)
I cannot find anywhere where this is documented though.