I have tried to follow this tutorial to connect to Google Analytics API. I have followed the instructions, step by step. I have Python 2.7 installed on my computer. I have installed Google client library. When I run the program, i get the following error in the terminal:
Traceback (most recent call last):
File "HelloAnalytics.py", line 6, in <module>
from oauth2client.client import SignedJwtAssertionCredential
ImportError: cannot import name SignedJwtAssertionCredentials
The line 6 that it referring to is:
from oauth2client.client import SignedJwtAssertionCredentials
I am at a complete lost. I looked at others who have had the same error, here, here, and here, but the solutions did not work. I have some programming knowledge, but compared to many of you, I am a noob.
The full code is here:
"""A simple example of how to access the Google Analytics API."""
import argparse
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
import httplib2
from oauth2client import client
from oauth2client import file
from oauth2client import tools
def get_service(api_name, api_version, scope, key_file_location,
service_account_email):
"""Get a service that communicates to a Google API.
Args:
api_name: The name of the api to connect to.
api_version: The api version to connect to.
scope: A list auth scopes to authorize for the application.
key_file_location: The path to a valid service account p12 key file.
service_account_email: The service account email address.
Returns:
A service that is connected to the specified API.
"""
f = open(key_file_location, 'rb')
key = f.read()
f.close()
credentials = SignedJwtAssertionCredentials(service_account_email, key,
scope=scope)
http = credentials.authorize(httplib2.Http())
# Build the service object.
service = build(api_name, api_version, http=http)
return service
def get_first_profile_id(service):
# Use the Analytics service object to get the first profile id.
# Get a list of all Google Analytics accounts for this user
accounts = service.management().accounts().list().execute()
if accounts.get('items'):
# Get the first Google Analytics account.
account = accounts.get('items')[0].get('id')
# Get a list of all the properties for the first account.
properties = service.management().webproperties().list(
accountId=account).execute()
if properties.get('items'):
# Get the first property id.
property = properties.get('items')[0].get('id')
# Get a list of all views (profiles) for the first property.
profiles = service.management().profiles().list(
accountId=account,
webPropertyId=property).execute()
if profiles.get('items'):
# return the first view (profile) id.
return profiles.get('items')[0].get('id')
return None
def get_results(service, profile_id):
# Use the Analytics Service Object to query the Core Reporting API
# for the number of sessions within the past seven days.
return service.data().ga().get(
ids='ga:' + profile_id,
start_date='7daysAgo',
end_date='today',
metrics='ga:sessions').execute()
def print_results(results):
# Print data nicely for the user.
if results:
print 'View (Profile): %s' % results.get('profileInfo').get('profileName')
print 'Total Sessions: %s' % results.get('rows')[0][0]
else:
print 'No results found'
def main():
# Define the auth scopes to request.
scope = ['https://www.googleapis.com/auth/analytics.readonly']
# Use the developer console and replace the values with your
# service account email and relative location of your key file.
service_account_email = '<Replace with your service account email address.>'
key_file_location = '<Replace with /path/to/generated/client_secrets.p12>'
# Authenticate and construct service.
service = get_service('analytics', 'v3', scope, key_file_location,
service_account_email)
profile = get_first_profile_id(service)
print_results(get_results(service, profile))
if __name__ == '__main__':
main()
Any help or direction would be appreciated.
The source repository was recently updated, and the Hello Analytics Guides have since also been updated to make use of the new code:
from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
...
credentials = ServiceAccountCredentials.from_p12_keyfile(
service_account_email, key_file_location, scopes=scope)
Where service_account_email is the email address of the service account you get from the dev console, and the key_file_locaiton is /the/path/to/key.p12, and scopes are the scopes you need to grant to the service account.
Please remember to add the service account email address as an authorized user of the Google Analytics view (profile) to which you wish it to have access.
Related
I am trying to get emails of all users of specific domain. I am able to get emails of user who created the service account (admin account), but during getting emails of other users of that domain I am facing HttpError 403 "Delegation denied for xxx#example.com"
I did the following steps:
Created a project, fetched a credentials.json file and using this file created a token.json file to authenticate requests,
Created service account and enabled domain wide delegation,
Collected the client id from that service account
and then delegate domain-wide authority to that service account using this guide link https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority
Here is example code of my request to get emails data of other users (using python):
from googleapiclient.discovery import build
from oauth2client import file
from httplib2 import Http
TOKEN_FILEPATH = "/path-to-token-file/"
def get_auth():
store = file.Storage(TOKEN_FILEPATH)
creds = store.get()
service = build('gmail', 'v1', http=creds.authorize(Http()))
return service
def get_emails():
user = 'xxx#example.com'
service = get_auth()
response = service.users().messages().list(userId=user).execute()
Thanks!
I am trying to access the Google Analytics report (v4) of a client, so I cannot generate my own client_secrets.json file. In the past I have used the oauth2client library to create a flow and storage object to authenticate via http. Current google documentation still uses the oauth2client library, which according to pypi.org (and google) was deprecated in September of 2018.
Here is the current code we are using to build the service:
import argparse
from apiclient.discovery import build
import httplib2
from oauth2client import client
from oauth2client import file
from oauth2client import tools
def get_service(api_name, api_version, scope, client_secrets_path):
"""Get a service that communicates to a Google API.
Args:
api_name: string The name of the api to connect to.
api_version: string The api version to connect to.
scope: A list of strings representing the auth scopes to authorize for the
connection.
client_secrets_path: string A path to a valid client secrets file.
Returns:
A service that is connected to the specified API.
"""
# 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=scope,
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(api_name + '.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(api_name, api_version, http=http)
return service
The current google documentation can be found here:
https://developers.google.com/analytics/devguides/config/mgmt/v3/quickstart/installed-py
How do I create this build without receiving specific client_secrets from the client and without using oauth2client?
If you use the service account flow, all you need to do is ask your client to add an additional user (which is just a api account connection) to their analytics account/property/view that you require access to, and it also means you don't need to construct an oauth2 flow.
There's step by step instructions of how to set this up and use it with the python library here:
https://developers.google.com/analytics/devguides/reporting/core/v4/quickstart/service-py
I've been having trouble over the past few days using the Google Directory API in the Admin SDK for Google Apps. The documentation leaves a lot to be desired and when I contacted Google Apps Enterprise support they indicated they do not support the API. I am using the most recent Python API client library provided by Google as they suggest this is the best way to go. I've logged in to the Google API Console and created a Service Account and downloaded the OAuth2 key. I've also turned on the Admin SDK in the console. Here is my code:
f = file("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-privatekey.p12", "rb")
key = f.read()
f.close()
credentials = SignedJwtAssertionCredentials(
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com",
key,
scope = "https://www.googleapis.com/auth/admin.directory.orgunit"
)
http = httplib2.Http()
http = credentials.authorize(http)
directoryservice = build("admin", "directory_v1", http=http)
orgunits = directoryservice.orgunits().list(customerId='XXXXXXX').execute(http=http)
pprint.pprint(orgunits)
Note that customerId is our Google Apps customer ID. I tried it with "my_customer" as Google seems to indicate should work when using an account that is super admin, but I receive the return "invalid customerId" when I try it that way. So I hardcoded our actual customerId.
When harcoded always receive the return "Login Required" but it seems as if the authentication process is working as the directory object gets created via the build command. Am I doing something wrong?
Note, I also read somewhere that sometimes the request needs to come from a domain account rather than the Service Account and to do this you need to add:
sub = "domain_account_superadmin#example.com"
In the SignedJwtAssertionCredentials call... which I tried, but then receive the message "access_denied"
Thanks in advance for suggestions.
See the google drive example here: https://developers.google.com/drive/delegation
Don't forget to delegate domain wide authority for the service account and scopes.
Here is an example for listing organization units via service account:
import sys
import apiclient.discovery
import oauth2client.client
import httplib2
import pprint
# see example for using service account here:
# https://developers.google.com/drive/delegation
def main (argv):
scopes = ('https://www.googleapis.com/auth/admin.directory.orgunit')
service_account_email = 'xxx#developer.gserviceaccount.com'
acting_as_user = 'yyy#zzz' # must have the privileges to view the org units
f = file('key.p12', 'rb')
key = f.read()
f.close()
credentials = oauth2client.client.SignedJwtAssertionCredentials(
service_account_email,
key,
scope=scopes,
sub=acting_as_user
)
http = httplib2.Http()
http = credentials.authorize(http)
directoryservice = apiclient.discovery.build('admin', 'directory_v1', http=http)
response = directoryservice.orgunits().list(customerId='my_customer').execute(http=http)
pprint.pprint(response)
if __name__ == '__main__':
main(sys.argv)
I'm looking for a good way to retrieve every emails address of my contacts from a google account for a "desktop" application in Python.
In a first time, I created an app via Google Code. I toggled Google Plus API, retrieving most of my user data, but not any of my contacts.
I started investigate, and I found a lot of stuff, but most of them was outdated.
I found a good way to retrieve my contacts, using gdata library but granting me a full read/write access on it, via https://www.google.com/m8/feeds with no feedback.
self.gd_client = gdata.contacts.client.ContactsClient(source='MyAppliName')
self.gd_client.ClientLogin(email, password, self.gd_client.source)
According to the official 'google contact api' google group, which migrated to stackoverflow, read only access is broken.
By the way, I'm not a huge fan of 'Trust my application, I use read only access, I swear."
I found the google api playground at https://developers.google.com/oauthplayground in which they use OAuth2.0 token with most of apis, including contact, toggling a webpage:
Google OAuth 2.0 Playground is requesting permission to:
Manage your contacts
According to this playground, it's possible to use OAuth2.0 with google contact api, but I have no idea how to add https:// www.google.com/m8/feeds to my scope, which doesn't appear on the list.
Is there an other way to do that ?
If this question is still open for you, here is some sample code how to use oauth2 and Google Contact API v3:
import gdata.contacts.client
from gdata.gauth import AuthSubToken
from oauth2client import tools
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
def oauth2_authorize_application(client_secret_file, scope, credential_cache_file='credentials_cache.json'):
"""
authorize an application to the requested scope by asking the user in a browser.
:param client_secret_file: json file containing the client secret for an offline application
:param scope: scope(s) to authorize the application for
:param credential_cache_file: if provided or not None, the credenials will be cached in a file.
The user does not need to be reauthenticated
:return OAuth2Credentials object
"""
FLOW = flow_from_clientsecrets(client_secret_file,
scope=scope)
storage = Storage(credential_cache_file)
credentials = storage.get()
if credentials is None or credentials.invalid:
# Run oauth2 flow with default arguments.
credentials = tools.run_flow(FLOW, storage, tools.argparser.parse_args([]))
return credentials
SCOPES = ['https://www.google.com/m8/feeds/', 'https://www.googleapis.com/auth/userinfo.email']
credentials = oauth2_authorize_application('client-secret.json', scope=SCOPES)
token_string = credentials.get_access_token().access_token
# deprecated!
# auth_token = AuthSubToken(token_string, SCOPES)
with open('client-secret.json') as f:
oauth2_client_secret = json.load(f)
auth_token = gdata.gauth.OAuth2Token(
client_id=oauth2_client_secret['web']['client_id'],
client_secret=oauth2_client_secret['web']['client_secret'],
scope=SCOPES,
user_agent='MyUserAgent/1.0',
access_token=credentials.get_access_token().access_token,
refresh_token=credentials.refresh_token)
client = gdata.contacts.client.ContactsClient(auth_token=auth_token)
query = gdata.contacts.client.ContactsQuery()
The request should look like:
https://accounts.google.com/o/oauth2/auth?
scope=https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds&
state=<myState>&
redirect_uri=<Redirect URI>&
response_type=code&
client_id=<my Client ID>&approval_prompt=force
This will obtain read/write access to the user's contacts.
I've been trying to make use of the Python Library to access the Google Sites API.
The first step requires a user to authorize our application, they recommend to use OAuth2 and they provide a library that can be found here.
At the end of the authorization process you end up with an OAuth2Credentials object.
The problem is, when I try to make requests to the Google Sites API, let's say I do:
import gdata.sites.client
client = gdata.sites.client.SitesClient(site=None, domain='mydomain.com')
I don't know how to make use of the OAuth2Credentials object.
I spent quite a few hours trying to do exactly this and finally found the answer in this blog post:
https://groups.google.com/forum/m/#!msg/google-apps-developer-blog/1pGRCivuSUI/3EAIioKp0-wJ
Here is a soup to nuts example of using the oauth2client together with the gdata API to access Google Sites including the 'Monkey Patching':
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run
import gdata.sites.client
import gdata.sites.data
SCOPE = 'https://sites.google.com/feeds/'
# client_secrets.json is downloaded from the API console:
# https://code.google.com/apis/console/#project:<PROJECT_ID>:access
# where <PROJECT_ID> is the ID of your project
flow = flow_from_clientsecrets('client_secrets.json',
scope=SCOPE,
redirect_uri='http://localhost')
storage = Storage('plus.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = run(flow, storage)
# 'Monkey Patch' the data in the credentials into a gdata OAuth2Token
# This is based on information in this blog post:
# https://groups.google.com/forum/m/#!msg/google-apps-developer-blog/1pGRCivuSUI/3EAIioKp0-wJ
auth2token = gdata.gauth.OAuth2Token(client_id=credentials.client_id,
client_secret=credentials.client_secret,
scope=SCOPE,
access_token=credentials.access_token,
refresh_token=credentials.refresh_token,
user_agent='sites-test/1.0')
# Create a gdata client
client = gdata.sites.client.SitesClient(source='sites-test',
site='YOUR.SITE',
domain='YOUR.DOMAIN',
auth_token=auth2token)
# Authorize it
auth2token.authorize(client)
# Call an API e.g. to get the site content feed
feed = client.GetContentFeed()
for entry in feed.entry:
print '%s [%s]' % (entry.title.text, entry.Kind())
My app is using .p12 key instead of flow, here is how I made it work after some tinkering:
from oauth2client.client import SignedJwtAssertionCredentials
import gdata.sites.client
import gdata.sites.data
scope = 'https://sites.google.com/feeds/'
key_file = 'xxxxxxxxxxxxxxxxxxx.p12'
with open(key_file) as f:
key = f.read()
credentials = SignedJwtAssertionCredentials(
'xxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com',
key,
sub='aleh#vaolix.com',
scope=[scope])
auth2token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
client = gdata.sites.client.SitesClient(source='sites-test',
domain='mydomain.com')
auth2token.authorize(client)
feed = client.GetSiteFeed()
for entry in feed.entry:
print entry.title.text