Is there any way to use a refresh token with Google directory service API?
I couldn't find any examples how to do that (I'm using Python).
I'm looking for something similar to the following code (this works for Google Adwords API), with previosly set credentials:
oauth2_client = oauth2.GoogleRefreshTokenClient(
CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN)
adwords_client = adwords.AdWordsClient(
DEVELOPER_TOKEN, oauth2_client, USER_AGENT, CLIENT_CUSTOMER_ID)
self.managed_customer_service = adwords_client.GetService(
'ManagedCustomerService', version='v201402')
For Directory API I found just the following code snippet, but I have no idea how I could use a refresh token with it:
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, 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)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
self.directory_service = build('admin', 'directory_v1', http=http)
My final goal is to authorize my application using just the refresh token and without having to open the browser, login and get a new token each time.
The Python client library can automatically store, load, and refresh credentials if you use a Storage object. The Gmail API Python Quickstart sample shows how to use a file storage, which saves the credentials to disk. Here are the relevant lines of code:
from oauth2client.file import Storage
from oauth2client.tools import run
...
# Location of the credentials storage file
STORAGE = Storage('gmail.storage')
...
# Try to retrieve credentials from storage or run the flow to generate them
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
credentials = run(flow, STORAGE, http=http)
There are additional storage classes built into the client library, or you can extend the Storage base class to implement you own.
Related
I'm a google blooger.
I upload 10 posts everyday by using python.
After uploaded 25 posts, I have to make a new credential.
This is code
CLIENT_SECRET = 'client_secret.json'
SCOPE = 'https://www.googleapis.com/auth/blogger'
STORAGE = Storage('credentials.storage')
# Start the OAuth flow to retrieve credentials
def authorize_credentials():
# Fetch credentials from storage
credentials = STORAGE.get()
# If the credentials doesn't exist in the storage location then run the flow
if credentials is None or credentials.invalid:
flow = flow_from_clientsecrets(CLIENT_SECRET, scope=SCOPE)
http = httplib2.Http()
credentials = run_flow(flow, STORAGE, http=http)
return credentials
credentials = authorize_credentials()
Do you have an idea there is any method without refreshing credential by mannual?
My python isnt the best but i think you might have an indentation issue. Have a look at this.
def initialize_blogger():
"""Initializes the blogger service object.
Returns:
analytics an authorized blogger service object.
"""
# Parse command-line arguments.
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[tools.argparser])
flags = parser.parse_args([])
# Set up a Flow object to be used if we need to authenticate.
flow = client.flow_from_clientsecrets(
CLIENT_SECRETS_PATH, scope=SCOPES,
message=tools.message_if_missing(CLIENT_SECRETS_PATH))
# Prepare credentials, and authorize HTTP object with them.
# If the credentials don't exist or are invalid run through the native client
# flow. The Storage object will ensure that if successful the good
# credentials will get written back to a file.
storage = file.Storage('blogger.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http=httplib2.Http())
# Build the service object.
service= build('blogger', 'v3', http=http)
return service
I created an python application that is using the Youtube api (so examples are in python, but doesn't really matter, the concepts should be the same). I managed to get it working where I can connect and make api calls. However, when I connect to the api, I have to define a flow that checks if a the credentials storage file exists. If it doesn't, then I have to manually sign in using the flow. After sign in the file (main.py-oauth2.json), is created with the token. I would like to be able to download the credentials without having to sign manually sign in. I was hoping there was a way to make a POST request for that token, like I have seen here, but I have been able to do this with Youtube api. Does anyone know how to implement the desired feature ?
main.py
flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,
scope=YOUTUBE_UPLOAD_SCOPE,
message=MISSING_CLIENT_SECRETS_MESSAGE)
storage = Storage(OAUTH_CREDENTIALS)
credentials = storage.get()
if credentials is None or credentials.invalid:
# manual / UI login
credentials = run_flow(flow, storage, args)
Trying to use a google service account throws 401 errors on upload.
credentials = Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=YOUTUBE_UPLOAD_SCOPES)
if credentials is None or credentials.expired:
raise ValueError('Invalid credentials')
return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
credentials=credentials)
...
status, response = insert_request.next_chunk()
# <HttpError 401 "Unauthorized">
Evidence this can be done
The oauth2client.service_account.ServiceAccountCredentials class is
only used with OAuth 2.0 Service Accounts. No end-user is involved
for these server-to-server API calls, so you can create this object
directly without using a Flow object.
youtube api
Oauth flow docs
https://developers.google.com/identity/protocols/OAuth2#serviceaccount
The problem is that most YouTube data is private user data. Being that it is private user data you must be authenticated as a user who has access to the data in question in order to access it. To do that we use Oauth2 and login to our account and get an access token and a refresh token returned.
The access token can be used to request data from the Youtube Api, the refresh token can be used to request a new access token when ever the access token expires (After an hour)
Normally i would say that you should consider using a service account. Services accounts are dummy users who can be preconfigured with access to user data. Unfortunately the Youtube api does not support service accounts.
What you should be doing and what i have done a number of times in the past is to authenticate your code once. Get the refresh token and save it. In the future whenever you wish to run your application you simply use the refresh token to request a new access token and you will be able to access the api. You wont have to manually type your login and password and consent to the access anymore everything can be done in the background using the refesh token.
Note: You will need to watch it there are some cases that can cause a refresh token to expire but you shouldn't worry for the most part they are good for as long as you continue to use them regularly.
I am not a python dev but found this
from oauth2client import client, GOOGLE_TOKEN_URI
CLIENT_ID = "client_id"
CLIENT_SECRET = "client_secret"
REFRESH_TOKEN = "refresh_token"
credentials = client.OAuth2Credentials(
access_token = None,
client_id = CLIENT_ID,
client_secret = CLIENT_SECRET,
refresh_token = REFRESH_TOKEN,
token_expiry = None,
token_uri = GOOGLE_TOKEN_URI,
token_ id = None,
revoke_uri= None)
http = credentials.authorize(httplib2.Http())
I followed the Google Sheet Python API Quickstart guide (https://developers.google.com/sheets/api/quickstart/python) and was able to get it working using their supplied code:
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
CLIENT_SECRET_FILE = 'my/path/client_secret.json'
APPLICATION_NAME = 'Google Sheets API Python Quickstart'
credential_path = 'my/path/sheets.googleapis.com-python-quickstart.json'
store = Storage(credential_path)
credentials = store.get()
## !!!!! Is this needed?
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
In the default setup I downloaded two JSON files:
client_secret.JSON
downloaded to project directory.
sheets.googleapis.com-python-quickstart.JSON
downloaded to ~/.credentials directory
The sheets.googleapis.com JSON file starts with:
"_module": "oauth2client.client".
Question 1: What is the purpose for each of these JSON files?
Question 2: Are both of these JSON files needed to successfully use the Google Sheets API?
I am thinking no, as I am able to get the API working without the client_secret.JSON file.
How about this answer? I think when you know the OAuth2 process for retrieving access token and refresh token, you can understand the meaning of both files. The flow for retrieving access token and refresh token using OAuth2 is as follows.
Flow :
Download client_secret.JSON from the API Console.
client_secret.JSON includes client_id, client_secret and redirect_uris.
Retrieve an authorization code using scopes and client_id from client_secret.JSON.
Retrieve access token and refresh token using the authorization code, client_id, client_secret and redirect_uris.
Retrieved access token, refresh token and other parameters are saved to the file of sheets.googleapis.com-python-quickstart.JSON.
Note :
When you run the Quickstart for the first time, the authorization process using your browser is launched. At that time, the script of Quickstart retrieves the authorization code using client_id and scopes, and then the access token and refresh token are retrieved using the authorization code, client_id, client_secret and redirect_uris.
After the first run of the Quickstart, the access token is retrieved by the refresh token from sheets.googleapis.com-python-quickstart.JSON. By this, retrieving the authorization code using browser is not required to do. So when there is sheets.googleapis.com-python-quickstart.JSON, client_secret.JSON is not required.
I think that this leads to an answer for your Question 2.
But, if you want to change scopes and/or credentials of client_secret.JSON, the authorization process using browser and retrieving the authorization code are required to do. For this, you have to remove sheets.googleapis.com-python-quickstart.JSON and authorize again. At that time, at Quickstart, client_secret.JSON is used again.
References :
Using OAuth 2.0 to Access Google APIs
Authorization for Google Services
If this is not useful for you, I'm sorry.
I'm using the Python API that google provides. What I want to do is just make sure that the access token doesn't expire. I have the refresh_token stored in the credentials file. I'm just not sure how to 'check' that the token is still good before making the call to the API and if need be refreshing it and re-storing it in the credentials file.
I did a test that even if I delete the access tokens from the credentials file that it rewrites them into it using the refresh token. I'm hoping that will work for expired access tokens as well.
Thanks
storage = Storage('cred_storage.txt')
credentials = storage.get()
if not credentials:
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, 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)
storage.put(credentials)
http = httplib2.Http()
http = credentials.authorize(http)
print http
service = build('admin', 'reports_v1', http=http)
print service
data_query = service.customerUsageReports().get(**{'date':'2015-01-07'})
feed = data_query.execute()
print feed
Simply check the case of expired access token and refresh your expired access token like this:
if credentials.access_token_expired:
credentials.refresh(httplib2.Http())
Tip: While developing this, you can test by editing the access token expiry date in the credentials text file and forcing it to be older than an hour
Also, in your code on the line where you are checking if not credentials:, you can better handle that case with:
if credentials is None or credentials.invalid:
I came across this question while trying to find a way to refresh an access token when construction a credentials object when using from_authorized_user_info. Unfortunately, the following code did not work for me:
credentials.refresh(httplib2.Http())
But I found this documentation from the Oauth library that works wonder. Shared below:
import google.auth.transport.requests
import requests
request = google.auth.transport.requests.Request()
credentials.refresh(request)
I am working with this simple Google API example:
import httplib2
from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run
# Path to the client_secret.json file downloaded from the Developer Console
CLIENT_SECRET_FILE = 'client_secret.json'
# Check https://developers.google.com/gmail/api/auth/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly'
# Location of the credentials storage file
STORAGE = Storage('gmail.storage')
# Start the OAuth flow to retrieve credentials
flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http()
# Try to retrieve credentials from storage or run the flow to generate them
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
credentials = run(flow, STORAGE, http=http)
# Authorize the httplib2.Http object with our credentials
http = credentials.authorize(http)
# Build the Gmail service from discovery
gmail_service = build('gmail', 'v1', http=http)
And seeing as I have already gone through the OAuth flow previously (in a different non-Python app) and have my refresh tokens, etc. I would like to skip the first portion of this example and either manually create the expected storage file gmail.storage or create the credentials object some other way.
The problem is I can't find any documentation about the expected format of this storage file, or what should be in it, or how to instantiate the credentials object in any other way. Sorry that I cannot show any work here, but I'm at a loss. Any point in the right direction would be greatly appreciated.
Very simple, apparently this works:
from oauth2client.client import GoogleCredentials
from oauth2client import GOOGLE_TOKEN_URI
access_token = None
token_expiry = None
token_uri = GOOGLE_TOKEN_URI
user_agent = 'Python client library'
revoke_uri = None
gCreds = GoogleCredentials(
access_token,
client_id,
client_secret,
refresh_token,
token_expiry,
token_uri,
user_agent,
revoke_uri=revoke_uri
)
As explained here: in Google Cloud Platform's github
you can also use a string to setup this. Specially a json string
import json
import os
from google.oauth2 import service_account
from google.cloud import translate
info = json.loads(os.environ['GOOGLE_APPLICATION_CREDENTIALS_JSON_STRING'])
creds = service_account.Credentials.from_service_account_info(info)
# Instantiates a client
translate_client = translate.Client(credentials=creds)
Please note that I used Google Translate's API for this example but it's the same logic.
There is a bit more explanation in this git issue too: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/4477
The oauth2client.file.Storage lib might be of interest to you:
from oauth2client.file import Storage
storage = Storage('gmail.storage')
credentials = storage.get()
storage.put(credentials)