3

I'm trying to access Google API services through a headless Linux server using Oauth2. I read through all the answers on this post: How do I authorise an app (web or installed) without user intervention? but none of them showed how to use the refresh token to generate an access token in python. pinnoyyid had a javascript example (https://stackoverflow.com/a/19766913/15713034) that went something like this:

function get_access_token_using_saved_refresh_token() { // from the oauth playgroundfunction get_access_token_using_saved_refresh_token() { // from the oauth playground const refresh_token = "1/0PvMAoF9GaJFqbNsLZQg-f9NXEljQclmRP4Gwfdo_0"; // from the API console const client_id = "559798723558-amtjh114mvtpiqis80lkl3kdo4gfm5k.apps.googleusercontent.com"; // from the API console const client_secret = "WnGC6KJ91H40mg6H9r1eF9L"; // from https://developers.google.com/identity/protocols/OAuth2WebServer#offline const refresh_url = "https://www.googleapis.com/oauth2/v4/token"; let refresh_request = { body:`grant_type=refresh_token&client_id=${encodeURIComponent(client_id)}&client_secret=${encodeURIComponent(client_secret)}& refresh_token=${encodeURIComponent(refresh_token)}`;, method: "POST", headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }) } 

JavaScript isn't really my best language, but I could decipher they were sending a POST request to the google server. So I tried to recreate the request in Python with the requests package:

 import requests result = requests.post("https://www.googleapis.com/oauth2/v4/token", body={'grant_type':'refresh-token', 'client_id':client_id, 'client_secret':client_secret, 'refresh_token': refresh_token}, headers={'Content-Type': 'application/x-www-form-urlencoded'}) 

And when I look at result it shows it has a 200 status code (success) but when I try to examine the response, there's nothing easy to read and I can't parse the result in JSON to get the access token. The other approach I tried was to spin up a Flask server using Google's suggested code: https://developers.google.com/identity/protocols/oauth2/web-server#python_5 but that doesn't work either because when I try to return the credentials from one of the functions (object that contains the access code) that won't return JSON no matter what. I'd prefer the post request method since it is cleaner and uses less code. Thanks!

2

3 Answers 3

2

In Python, one approach is to use requests-oauthlib to perform the Backend Application Flow. This is useful when you don't have a front-end to redirect someone to, in order to approve fetching a token.

Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately, using both methods provided result in this issue when I get to oauth.fetch_token() argument: oauthlib.oauth2.rfc6749.errors.UnsupportedGrantTypeError: (unsupported_grant_type) Invalid grant_type: client_credentials
This is probably because Google's Oauth doesn't accept this client_credentials data type which is what HTTPBasicAuth() is. Do you know another way I can call .fetch_token()? Perhaps by using the 'body' or 'headers' parameters in fetch_token()? Reference: docs.authlib.org/en/latest/client/api.html#authlib.integrations.requests_client.OAuth2Session.
Here's a (somewhat unhelpful) related SO post: stackoverflow.com/questions/46751901/…
1

This website (https://community.atlassian.com/t5/Bitbucket-questions/Refresh-Tokens-using-Python-requests/qaq-p/1213162) says solution could be something like this:

 import requests auth = ("<consumer_id>", "<consumer_secret>") params = { "grant_type":"refresh_token", "refresh_token":"<your_refresh_token_here>" } url = "https://www.googleapis.com/oauth2/v4/token" ret = requests.post(url, auth=auth, data=params) #note data=params, not params=params 

Comments

1

Since none of the solutions above worked, I had to finally just give up and use a service account.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.