Use Google API with a token [Django & AllAuth] - python

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)

Related

Firebase Admin SDK - Python

Recently the FB Admin SDK was introduced for Python as well, and here is a repo with some samples.
It's nice I can authenticate using credentials, and finally I have a firebase_admin authenticated which can create Custom Tokens too. But how can it help to do requests for the REST API e.g? Can I retrieve my authentication token and set it as Authorization header maybe to do API requests?
You should be able to get an OAuth token by calling the get_access_token() method on your credential, and then pass it to the REST API as described here.
However, in the v1.0.0 of the Python Admin SDK, the returned credential does not contain the Firebase scopes. Therefore the OAuth token obtained from the credential will not readily work with the REST API. This is a bug, and it will be addressed in a future release. In the meantime you can use the following trick:
from firebase_admin import credentials
scopes = [
'https://www.googleapis.com/auth/firebase.database',
'https://www.googleapis.com/auth/userinfo.email'
]
cred = credentials.Certificate('path/to/serviceKey.json')
token = cred.get_credential().create_scoped(scopes).get_access_token().access_token
# Pass token to REST API
In a future release, once the bug has been fixed, you will be to do the following:
from firebase_admin import credentials
cred = credentials.Certificate('path/to/serviceKey.json')
token = cred.get_access_token().access_token
# Pass token to REST API

How to authorize a Python Google API client service given an OAuth2 access_token?

I have implemented the python-social-auth library for Google OAuth2 in my Django project, and am successfully able to log users in with it. The library stores the access_token received in the response for Google's OAuth2 flow.
My question is: use of the google-api-python-client seems to rely on creating and authorizing a credentials object, then using it to build an API service like so:
...
# send user to Google consent URL, get auth_code in response
credentials = flow.step2_exchange(auth_code)
http_auth = credentials.authorize(httplib2.Http())
from apiclient.discovery import build
service = build('gmail', 'v1', http=http_auth)
# use service for API calls...
Since I'm starting with an access_token provided by python-social-auth, how do I create & authorize the API client service for future API calls?
Edit: to clarify, the code above is from the examples provided by Google.
Given you already have the OAuth2 access token you can use the AccessTokenCredentials class.
The oauth2client.client.AccessTokenCredentials class is used when you have already obtained an access token by some other means. You can create this object directly without using a Flow object.
Example:
import httplib2
from googleapiclient.discovery import build
from oauth2client.client import AccessTokenCredentials
credentials = AccessTokenCredentials(access_token, user_agent)
http = httplib2.Http()
http = credentials.authorize(http)
service = build('gmail', 'v1', http=http)
You can check examples provided by Google Guide API, for example: sending email via gmail application, https://developers.google.com/gmail/api/guides/sending
If you have an already refreshed latest access token which is not expired, then you can get service variable as:
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
creds = Credentials("<ACCESS_TOKEN>")
service = build('gmail', 'v1', credentials=creds)
# Call the Gmail API

Google OAuth2client - invalid_grant: Token has been revoked

I'm writing a basic app that prints out projects in Google's Cloud Resources Manager using this method:
https://cloud.google.com/resource-manager/reference/rest/v1/projects/list
Yesterday it worked but I revoked the token and the code doesn't prompt to re-authorize.
from googleapiclient import discovery from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)
projects = service.projects() request = projects.list() while request is not None:
response = request.execute()
for project in response['projects']:
print project
request = projects.list_next(previous_request=request, previous_response=response)
File "oauth2client/client.py", line 834, in _do_refresh_request
raise HttpAccessTokenRefreshError(error_msg, status=resp.status) oauth2client.client.HttpAccessTokenRefreshError: invalid_grant: Token
has been revoked.
I think there's a way to tell the client to check if the token is valid and pop the user out to a browser if not, but can't seem to get the code to do it. Any help appreciated ;)
Since this code uses application default credentials, the gcloud command is how I get a new token:
gcloud beta auth application-default login
Although it would be nice if there was a way to do this in code in the event the token is revoked again.
Suddenly yesterday we faced a similar issue in Google OAuth2 connection from gerrit code review. So just wanted to share this as it might be related to you. Refer this github issue & its commit made for gerrit-oauth-provider

Authorizing a python script to access the GData API without the OAuth2 user flow

I'm writing a small python script that will retrieve a list of my Google Contacts (using the Google Contacts API) and will randomly suggest one person for me to contact (good way to automate keeping in touch with friends!)
This is just a standalone script that I plan to schedule on a cron job. The problem is that Google seems to require OAuth2 style authentication, where the user (me) has to approve the access and then the app receives an authorization token I can then use to query the user's (my) contacts.
Since I'm only accessing my own data, is there a way to "pre-authorize" myself? Ideally I'd love to be able to retrieve some authorization token and then I'd run the script and pass that token as an environment variable
AUTH_TOKEN=12345 python my_script.py
That way it doesn't require user input/interaction to authorize it one time.
The implementation you're describing invokes the full "three-legged" OAuth handshake, which requires explicit user consent. If you don't need user consent, you can instead utilize "two-legged" OAuth via a Google service account, which is tied to an application, rather than a user. Once you've granted permission to your service account to access your contacts, you can use the oauth2client ServiceAccountCredentials class to directly access GData without requiring user consent.
Here's the two-legged authentication example from the Google service account documentation:
import json
from httplib2 import Http
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
scopes = ['https://www.googleapis.com/auth/sqlservice.admin']
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'service-account.json', scopes)
sqladmin = build('sqladmin', 'v1beta3', credentials=credentials)
response = sqladmin.instances().list(project='examinable-example-123').execute()
print response

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