Google Admin SDK Error 401 when trying to authorize - google-admin-sdk

I am using the Google Admin SDK Reports V1 Api to gather all admin activities from the Google Apps admin panel.
My Google Api python client was recently updated to version "google-api-python-client (1.5.1)"
Previously I was using the following:
from oauth2client.client import SignedJwtAssertionCredentials
serviceAccountEmail = "blahblablah1233324#developer.gserviceaccount.com"
key = "google-apps-file.p12"
scopes = ['https://www.googleapis.com/auth/admin.reports.audit.readonly']
credentials = SignedJwtAssertionCredentials(
serviceAccountEmail, key, scope=scopes, sub=userEmail)
Then Google dropped support for SignedJwtAssertionCredentials. So I switched to this.
from oauth2client.service_account import ServiceAccountCredentials
serviceAccountEmail = "blahblablah1233324#developer.gserviceaccount.com"
key = "google-apps-file.p12"
scopes = ['https://www.googleapis.com/auth/admin.reports.audit.readonly']
credentials = ServiceAccountCredentials.from_p12_keyfile(
serviceAccountEmail, key, scopes=scopes)`
Ok so this should be a relatively easy small code change, however when I ran the code I get the following error.
File "/usr/local/lib/python2.7/site-packages/oauth2client/util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/googleapiclient/http.py", line 832, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 401 when requesting https://www.googleapis.com/admin/reports/v1/activity/users/all/applications/admin?alt=json returned "Access denied. You are not authorized to read activity records.">
So no permissions have changed, one thing I am noticing though is the original code is asking for a sub=userEmail (which is an account to impersonate, that account would have specific admin privileges over the Google Apps domain.)
It would make sense that I would get the 401 however there is no mention of a sub=userEmail parameter in the new documentation.

I realized what I was missing.
Originally I had
f = open(serviceAccountKeyLocation, 'rb')
key = f.read()
f.close()
# Packaging up the auth parameters to pass along with the request.
credentials = SignedJwtAssertionCredentials(serviceAccountEmail, key, scope=scopes, sub=userEmail)
http = credentials.authorize(http)
return http
I then did some reading up and further research.
Then replaced it with this.
credentials = ServiceAccountCredentials.from_p12_keyfile(serviceAccountEmail,
serviceAccountKeyLocation,
scopes=scopes)
delegate_credentials = credentials.create_delegated(userEmail) # this fixes the sub user
http = delegate_credentials.authorize(http)
return http
The version of the Google Api python client I was running was still making use of from oauth2client.client import SignedJwtAssertionCredentials while the new updated version uses from oauth2client.service_account import ServiceAccountCredentials.

Related

Flask Facebook Login using Oauthlib - redirect problem

I would like to implement Facebook login using Flask.
Here is the function which is called to request service from Facebook
#users_view.route('/facebook/')
def facebook():
credentials = current_app.config['OAUTH_CREDENTIALS']['facebook']
f_client = WebApplicationClient(credentials['id'])
authorization_endpoint = 'https://www.facebook.com/dialog/oauth'
request_uri = f_client.prepare_request_uri(
authorization_endpoint,
redirect_uri=request.base_url + "/auth",
scope=["email"],
auth_type = "reauthenticate",
)
print("REQUEST: {}".format(request_uri))
return redirect(request_uri)
#users_view.route("/facebook/auth")
def facebook_callback():
credentials = current_app.config['OAUTH_CREDENTIALS']['facebook']
f_client = WebApplicationClient(credentials['id'])
token_endpoint = 'https://graph.facebook.com/oauth/access_token'
code = request.args.get("code")
token_url, headers, body = f_client.prepare_token_request(
token_endpoint,
authorization_response=request.url,
redirect_url=request.base_url,
code=code
)
print("ALL: url:{} headers:{} url:{} ".format(token_url, headers, body))
Which forwards me to this URL:
https://www.facebook.com/dialog/oauth?response_type=code&client_id=5453357158093262&redirect_uri=https%3A%2F%2F127.0.0.1%3A5000%2Fuser%2Ffacebook%2F%2Fauth&scope=email&auth_type=reauthenticate&ret=login&fbapp_pres=0&logger_id=1cc03c7d-9a19-43ba-978c-4ed8cb7aa559&tp=unspecified&cbt=1663931173196&ext=1663941992&hash=AeaYsntT-4HEQj4ZtfI
That throws the following Error:
In my Facebook developers account, I have following redirect URL configuration:
Kindly, advice how can I fix this issue.
Facebook API is expecting the requester to use HTTPS as you've set in your Facebook Developer Account.
Probably you are running your flask app using HTTP protocol (not HTTPS) while on your Facebook Developer account you did white-list only HTTPS, but since you didn't specify HTTP it will be rejected.
A) You cannot allow HTTP(without S) from Facebook Panel because Oauth2 need HTTPS.
Try:
B) Install pyOpenSSL
pip3 install pyOpenSSL
Create ssl_my_app.py and run with ssl_context:
from flaskr import create_app
from flask import current_app, g
import sqlite3 # if using databases
app = create_app()
with app.app_context():
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
with current_app.open_resource('schema.sql') as f:
g.db.executescript(f.read().decode('utf-8'))
app.run(ssl_context='adhoc')
run the app using ssl_my_app.py:
python3 ssl_my_app.py
This will run the app using HTTPS (self-signed certificate).
So when you call Facebook API your application's request will be in the white-list.

How to authenticate DCM account by using service account?

I'm trying to download the report from DCM by using python client library. I'm using service account and using this link code this!. I have followed all the steps to set up the service account file which is mentioned in DCM api url, but I'm getting below error while running the code.
Traceback (most recent call last):
File "/usr/bin/anaconda/envs/py35/lib/python3.5/site-packages/oauth2client/clientsecrets.py", line 86, in _validate_clientsecrets
(client_type, client_info), = clientsecrets_dict.items()
ValueError: too many values to unpack (expected 1)
I'm using below service account file to connect to the DCM api and download the reports. This is the process I'm trying to set up so that on daily basis the reports get download automatically without any manual intervention.
import argparse
import sys
from googleapiclient import discovery
import httplib2
from oauth2client import client
from oauth2client import tools
from oauth2client.service_account import ServiceAccountCredentials
# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('path_to_service_account_json_file',help='Path to the service account JSON file to use for authenticating.')
argparser.add_argument('-i','--impersonation_email',help='Google account email to impersonate.')
# The OAuth 2.0 scopes to request.
OAUTH_SCOPES = ['https://www.googleapis.com/auth/dfareporting']
def main(argv):
# Retrieve command line arguments.
parser = argparse.ArgumentParser(description=__doc__,formatter_class=argparse.RawDescriptionHelpFormatter,parents=[tools.argparser, argparser])
flags = parser.parse_args(argv[1:])
# Authenticate using the supplied service account credentials
http = authenticate_using_service_account(flags.path_to_service_account_json_file,flags.impersonation_email)
# Construct a service object via the discovery service.
service = discovery.build('dfareporting', 'v3.3', http=http)
try:
# Construct the request.
request = service.userProfiles().list()
# Execute request and print response.
response = request.execute()
for profile in response['items']:
print('Found user profile with ID %s and user name "%s".' %(profile['profileId'], profile['userName']))
except client.AccessTokenRefreshError:
print('The credentials have been revoked or expired, please re-run the ''application to re-authorize')
def authenticate_using_service_account(path_to_service_account_json_file,impersonation_email):
"""Authorizes an httplib2.Http instance using service account credentials."""
# Load the service account credentials from the specified JSON keyfile.
credentials = ServiceAccountCredentials.from_json_keyfile_name(path_to_service_account_json_file,scopes=OAUTH_SCOPES)
# Configure impersonation (if applicable).
if impersonation_email:
credentials = credentials.create_delegated(impersonation_email)
# Use the credentials to authorize an httplib2.Http instance.
http = credentials.authorize(httplib2.Http())
return http
if __name__ == "__main__":
main(sys.argv)
TypeError: cannot instantiate ctype 'EVP_MD_CTX' of unknown size

Trying to Access Google Directory API via p12 throws not authorized error

from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
import json
import base64
import httplib2
f = file('tara1-553d334b8702.p12', 'rb')
key = f.read()
f.close()
credentials = ServiceAccountCredentials.from_p12_keyfile(
'googleapptara#tara1-167105.iam.gserviceaccount.com',
'tara1-554d335b8702.p12',
private_key_password='notasecret',
scopes=['https://www.googleapis.com/auth/admin.directory.user.readonly','https://www.googleapis.com/auth/admin.directory.user']
)
delegated_credentials=credentials.create_delegated('tara.gurung#orgemail.net)
http = httplib2.Http()
http = credentials.authorize(http)
DIRECOTORY = build('admin', 'directory_v1', credentials=credentials)
maxResults=10,orderBy='email').execute()
results = DIRECOTORY.users().list(domain='domainnamehere.net').execute()
users = results.get('users', [])
print users
Here ,I am trying to do the server to server authentication using the p12 security file and trying to grab all the users in the domain.
I have successfully fetched the users list by 3legs authentication,by authorizing from the browswer in the same account
But this way it's throwing me the following errors.
File "testing.py", line 41, in <module>
results = DIRECOTORY.users().list(domain='domainemailhere.net').execute()
File "/home/tara/taraproject/scripttesting/virtualenvforGapi/local/lib/python2.7/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/tara/taraproject/scripttesting/virtualenvforGapi/local/lib/python2.7/site-packages/googleapiclient/http.py", line 840, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/admin/directory/v1/users?domain=nepallink.net&alt=json returned "Not Authorized to access this resource/api">
SETUP DONE:
I have a super admin level access in the admin console.
I have also added
the scope via security>showmore>advance>manageipclient>authorize
Added the user id and scope
https://www.googleapis.com/auth/admin.directory.user.readonly
https://www.googleapis.com/auth/admin.directory.user
Added the users permission in service console and made a owner.
Admin SDK is Enabled
Where exactly am I missing the things. Why does it says I have no authority to access the resources/api
I see you are using delegated_credentials. Have you used it??
Change following line:
DIRECOTORY = build('admin', 'directory_v1', credentials=credentials)
to
DIRECOTORY = build('admin', 'directory_v1', credentials=delegated_credentials)

Google Cloud API: Forbidden to access Enabled API using Service Account key

I am having issues use Service Account P12 Key and getting HttpError 403.
However, I do not have this issue if I use Web OAuth using Client ID and Secret. However, I am creating as Service to Service application.
Google Cloud API JSON is enabled.
import os
from httplib2 import Http
from pprintpp import pprint
from oauth2client.client import SignedJwtAssertionCredentials
from apiclient.discovery import build
from googleapiclient.errors import HttpError
SITE_ROOT = \
os.path.dirname(os.path.realpath(__file__))
P12_FILE = \
"REDACTED-0123456789.p12"
P12_PATH = os.path.join(SITE_ROOT, P12_FILE)
pprint(P12_PATH)
SCOPE = \
'https://www.googleapis.com/auth/devstorage.read_only'
PROJECT_NAME = \
'mobileapptracking-insights'
BUCKET_NAME = \
'pubsite_prod_rev_0123456789'
CLIENT_EMAIL = \
'REDACTED-service#foo-bar-0123456789.iam.gserviceaccount.com'
private_key = None
with open(P12_PATH, "rb") as p12_fp:
private_key = p12_fp.read()
credentials = SignedJwtAssertionCredentials(
CLIENT_EMAIL,
private_key,
SCOPE)
http_auth = credentials.authorize(Http())
storage = build('storage', version='v1', http=http_auth)
request = storage.objects().list(bucket=BUCKET_NAME)
try:
response = request.execute()
except HttpError as error:
print("HttpError: %s" % str(error))
raise
except Exception as error:
print("%s: %s" % (error.__class__.__name__, str(error)))
raise
print(response)
Error message:
HttpError: <HttpError 403 when requesting https://www.googleapis.com/storage/v1/b/pubsite_prod_rev_0123456789/o?alt=json returned "Forbidden">
What do I need to do to resolve this issue?
Your code looks fine (I just pasted it, changed the appropriate constants, and successfully ran it).
I would double-check:
That your client email is the correct one for the p12 key
That the bucket you're listing is accessible to that service account
Some other things you could do to help you figure out where the problem is:
Verify that you can list the public uspto-pair bucket
import httplib2 and set httplib2.debuglevel = 1, and verify that the requests that are being made are the expected ones.
The issue was that I had not assigned access permissions to the service's 'client email' through the Google Play Developers Console > Settings > USER ACCOUNTS & RIGHTS

google admin sdk directory api 403 python

i want to use admin sdk directory api to create eamil account of users.
i am using google-api-python-client-1.2 library.
in folder /samples/service_account/tasks.py works for me.
but when i chance that file to list users from admin directory api it doesn't works and throws errors.
below is the code i am using.
import httplib2
import pprint
import sys
import inspect
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
def main(argv):
f = file('my-privatekey.p12', 'rb')
key = f.read()
f.close()
credentials = SignedJwtAssertionCredentials(
'my#developer.gserviceaccount.com',
key,
scope=['https://www.googleapis.com/auth/admin.directory.user', 'https://www.googleapis.com/auth/admin.directory.user.readonly'])
http = httplib2.Http()
http = credentials.authorize(http)
service = build("admin", "directory_v1", http)
list_of_apis = service.users().list(domain='mydomain.com').execute(http=http)
pprint.pprint(list_of_apis)
if __name__ == '__main__':
main(sys.argv)
when i run the above code i get below errors.
$python tasks.py
No handlers could be found for logger "oauth2client.util"
Traceback (most recent call last):
File "tasks.py", line 77, in <module>
main(sys.argv)
File "tasks.py", line 66, in main
list_of_apis = service.users().list(domain='messycoders.com').execute(http=http)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/apiclient/http.py", line 723, in execute
raise HttpError(resp, content, uri=self.uri) apiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/admin/directory/v1/users?domain=messycoders.com&alt=json returned "Not Authorized to access this resource/api">
Try:
credentials = SignedJwtAssertionCredentials(
'my#developer.gserviceaccount.com',
key,
sub='superadmin#mydomain.com',
scope=['https://www.googleapis.com/auth/admin.directory.user',])
You don't need both scopes, use readonly if you're doing read operations only, use the above if you're doing read and write.
sub= defines which Google Apps account the service account should impersonate to perform the directory operations, it's necessary and the account needs to have the right permissions.
Lastly, be sure that you've granted the service account's client_id access to the directory scopes you need in the Control Panel. The steps to do this are listed in the Drive documentation, just sub in the correct scope(s) for Admin Directory.