Google App Engine (Python), OAuth2, Service Accounts, User Delegation, Youtube Service - python

I'm using the Youtube Data API (v3), along with the Python client library on Google App Engine.
Here is a simple snippet of code that fails:
kwargs = {'prn' : google_oauth_user_email}
credentials = SignedJwtAssertionCredentials(google_oauth_email, google_oauth_key, scope=YOUTUBE_SCOPE, **kwargs)
http = credentials.authorize(httplib2.Http())
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, http=http)
request = youtube.channels().list(part="snippet", id="25")
response = request.execute(http=http)
which results in:
Failed to retrieve access token: {
"error" : "access_denied"
}
If I remove the kwargs so as not to delegate user access, this request works fine. The Service Account is registered against the same user account to which delegation is being requested.
My ultimate goal is to upload videos (on behalf of that user) using the Server-to-Server two-legged OAuth2 flow.
Can anybody explain to me why delegation to the same user account as that which the Service Account is already registered fails, and how I might be able to allow it?

Related

How to create user in Google Admin with Service Account (server side)

I am trying to create a user in Google Admin via API
(google admin)
Things I have done:
create service account and credentials
installed sdk lib
read multiple docs on service account/Oauth credentials, google sdk authen., admin api
code
class Gcp:
def __init__(self):
SERVICE_ACCOUNT_FILE = "core/gcp/XXX.json"
read_domain_scope = 'https://www.googleapis.com/auth/admin.directory.domain.readonly'
admin_user_scope = 'https://www.googleapis.com/auth/admin.directory.user'
read_ou_scope = 'https://www.googleapis.com/auth/admin.directory.orgunit.readonly'
SCOPES = [read_domain_scope, admin_user_scope, read_ou_scope,]
self.credential = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
def list_user(self):
res = googleapiclient.discovery.build('users', 'v1', credentials=self.credential)
return 'OK'
Problems:
I can not find a document which specify how I can create user in google admin via SDK, I mean I've found the REST api doc
But I seems that I need to authenticate through OAuth2 for the REST calls.
Is there a way to get this (create user and assign domain/organization unit) done with just service account credential file with SDK?

GTasks API Service Account: Client is unauthorized to retrieve access tokens using this method

I have a service account with Domain wide delegation and its been working fine for Calendar APIs. I am able to impersonate as other users within the organization to CRUD events in Google Calendar without the Consent Screen. Now i'm trying to consume GTasks API but getting error.
For GTasks
credentials = service_account.Credentials.from_service_account_file('service-account.json', scopes=['https://www.googleapis.com/auth/tasks'])
delegated_credentials = credentials.with_subject('username#company.com')
service = build('tasks', 'v1', credentials=delegated_credentials)
tasklists = service.tasklists().list(maxResults=10).execute()
and got below error.
('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.', '{\n "error": "unauthorized_client",\n "error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."\n}')
For GCalendar, working fine
credentials = service_account.Credentials.from_service_account_file('service-account.json', scopes=['https://www.googleapis.com/auth/calendar'])
delegated_credentials = credentials.with_subject('username#company.com')
service = build('calendar', 'v3', credentials=delegated_credentials)
events = service.events().list(calendarId=SUBJECT,timeMin=now,maxResults=10,orderBy='startTime',singleEvents=True).execute()
I'm using this lib https://github.com/googleapis/google-api-python-client. Any hint what's wrong here?
Not all APIs support domain-wide delegation. If they do, you will see it mentioned in the Auth documentation.
The Calendar API supports domain-wide delegation, and the Tasks API does not.
https://developers.google.com/calendar/auth
https://developers.google.com/tasks/auth
Google Calendar and Tasks both support domain wide-delegation, I am using that. My suggestion is:
Check if your developer console has enabled Google Tasks API
Check if you've added Google Tasks into your API permission scope in your G Suite admin dashboard. May refer https://developers.google.com/identity/protocols/OAuth2ServiceAccount for more detail

Use Google API with a token [Django & AllAuth]

I am using AllAuth on my Django app to manage user authentication. With that my users can connect their Google accounts and i get a google API token (with appropriate scopes).
I would like to use that token to access google APIs (Calendar v3 in my case) with that token, as my user already used OAuth2 to sign-in on my website, and gave me access to the calendar API.
Google only gives the full process on their website (from auth to api), is there a way to build my idea, or is it simply impossible?
i have tries drive = build('calendar', 'v3', credentials=credentials) as said here but "credentials" needs to be part of an oauth2client and not just a simple string token.
Thank you for your precious time.
Simon
I know its an older question but I finally found something that worked for me. After a successful authentication with allauth, I did this to get the client token and then build the service.
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
from allauth.socialaccount.models import SocialToken, SocialApp
...
# request is the HttpRequest object
token = SocialToken.objects.get(account__user=request.user, account__provider='google')
credentials = Credentials(
token=token.token,
refresh_token=token.token_secret,
token_uri='https://oauth2.googleapis.com/token',
client_id='client-id', # replace with yours
client_secret='client-secret') # replace with yours
service = build('calendar', 'v3', credentials=credentials)

Python Google CustomerLicense "Not authorized to access the application ID"

I am trying to check if the user has installed my marketplace app
from oauth2client.client import SignedJwtAssertionCredentials
import json
from httplib2 import Http
from apiclient.discovery import build
fname = 'my-creds.json'
scope = [
'https://www.googleapis.com/auth/appsmarketplace.license'
]
applicationId='12345678'
customerId='mydomain.com'
json_key = json.load(open(fname))
credentials = SignedJwtAssertionCredentials(json_key['client_email'], json_key['private_key'], scope)
http_auth = credentials.authorize(Http())
appsmarket = build('appsmarket', 'v2', http=http_auth)
response = appsmarket.customerLicense().get(applicationId=applicationId, customerId=customerId).execute()
print response
I have created a service account in the same project as my app in Google console.
But I keep getting
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/appsmarket/v2/customerLicense/471879773528/ashish%40noodletools.com?alt=json returned "Not authorized to access the application ID">
Do you add service account to your domain's authorized API clients in security section?
Look at Delegating domain-wide authority to the service account here: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
To delegate domain-wide authority to a service account, an administrator of the Google Apps domain must complete the following steps:
Go to your Google Apps domain’s Admin console.
Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls. If you can't see the controls, make sure you're signed in as an administrator for the domain.
Select Show more and then Advanced settings from the list of options.
Select Manage API client access in the Authentication section.
In the Client Name field enter the service account's Client ID.
In the One or More API Scopes field enter the list of scopes that your application should be granted access to.
Click Authorize.
Your application now has the authority to make API calls as users in your domain (to "impersonate" users). When you prepare to make authorized API calls, you specify the user to impersonate.

Can't authorize with google plus API

I am trying to authorize my app using google plus. However, everything I've tried always gives me a 404 when I use the people service and attempt to get 'me', except when I log in with the user who created the Google+ API app. It doesn't make any sense to my why that would be the case.
from httplib2 import Http
from apiclient.discovery import build
credential = gp_client.step2_exchange(request.REQUEST)
http = Http()
http = credential.authorize(http)
service = build("plus", "v1", http=http)
o = service.people().get(userId='me').execute()
The same is also true when I use the Google+ explorer:
http://code.google.com/apis/explorer/#_s=plus&_v=v1&_m=people.get&fields=emails
If I switch to private with the user who created the API, then I can fetch 'me', but if I authorize another user, then I can't fetch 'me'.
Any ideas what is happening?
Finally figured out what this was. Google lets you authorize any google account for an app. However, if the authorizing user hasn't upgraded to Google+, when the app makes its first Google+ API request, the request will 404. This is mind boggling, because when I setup the OAuth2WebServerFlow I specified "plus.me" as the scope... IMHO Google should tell the user to upgrade to Google+ when they try to authorize this OAuth request.
gp_client = OAuth2WebServerFlow(
settings.GOOGLE_PLUS_CONSUMER_ID,
settings.GOOGLE_PLUS_CONSUMER_SECRET,
scope='https://www.googleapis.com/auth/plus.me',
)

Categories