7

I've spent hours trying to troubleshoot how to get oauth2 tokens using the python request library. What am I doing wrong?

  r=requests.post("https://accounts.google.com/o/oauth2/token",
                            headers={
                                'content-type':'application/x-www-form-urlencoded'},
                            params={
                                'code':request.GET['code'],
                    'client_id':'11111111111.apps.googleusercontent.com',
                                'client_secret':'my secert',
                                'redirect_uri':'http://localhost/etc'
                                'grant_type':'authorization_code'})
1

3 Answers 3

3

The data for the request must be sent in the body NOT IN the query string

change params= to data= in your code.

See this discussion for details: https://groups.google.com/forum/#!topic/oauth2-dev/ahP0cz2ao0o

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

Comments

3

This is a very late answer, but might be useful to some.

I have got Google OAuth2 flow working nicely with requests in this simple class

from requests.adapters import HTTPAdapter
from requests_oauthlib import OAuth2Session
from urllib3.util.retry import Retry
import os

from yaml import load, dump, YAMLError

try:
    from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
    from yaml import Loader, Dumper


# OAuth endpoints given in the Google API documentation
authorization_base_url = "https://accounts.google.com/o/oauth2/v2/auth"
token_uri = "https://www.googleapis.com/oauth2/v4/token"

'''
Defines a very simple class to handle google api authorization flow
for the requests library. Includes saving the token and automatic
token refresh.
giles 2018
'''


class Authorize:
    def __init__(self, scope, token_file, secrets_file):
        self.scope = scope
        self.token_file = token_file
        self.session = None
        self.token = None
        try:
            with open(secrets_file, 'r') as stream:
                all_yaml = load(stream, Loader=Loader)
            secrets = all_yaml['installed']
            self.client_id = secrets['client_id']
            self.client_secret = secrets['client_secret']
            self.redirect_uri = secrets['redirect_uris'][0]
            self.token_uri = secrets['token_uri']
            self.extra = {
                'client_id': self.client_id,
                'client_secret': self.client_secret}

        except (YAMLError, IOError):
            print('missing or bad secrets file: {}'.format(secrets_file))
            exit(1)

    def load_token(self):
        try:
            with open(self.token_file, 'r') as stream:
                token = load(stream, Loader=Loader)
        except (YAMLError, IOError):
            return None
        return token

    def save_token(self, token):
        with open(self.token_file, 'w') as stream:
            dump(token, stream, Dumper=Dumper)
        os.chmod(self.token_file, 0o600)

    def authorize(self):
        token = self.load_token()

        if token:
            # force refresh on load token.expires_in = -30
            #  todo this is no longer in the token ??
            #   how to force update?
            self.session = OAuth2Session(self.client_id, token=token,
                                         auto_refresh_url=self.token_uri,
                                         auto_refresh_kwargs=self.extra,
                                         token_updater=self.save_token)
        else:
            print(self.scope)
            self.session = OAuth2Session(self.client_id, scope=self.scope,
                                         redirect_uri=self.redirect_uri,
                                         auto_refresh_url=self.token_uri,
                                         auto_refresh_kwargs=self.extra,
                                         token_updater=self.save_token)

            # Redirect user to Google for authorization
            authorization_url, _ = self.session.authorization_url(
                authorization_base_url,
                access_type="offline",
                prompt="select_account")
            print('Please go here and authorize,', authorization_url)

            # Get the authorization verifier code from the callback url
            response_code = input('Paste the response token here:')

            # Fetch the access token
            self.token = self.session.fetch_token(
                self.token_uri, client_secret=self.client_secret,
                code=response_code)
            self.save_token(self.token)

        # note this does retries on POST as well
        # CAUTION - this might not be desirable for all applications
        retries = Retry(total=5,
                        backoff_factor=0.1,
                        status_forcelist=[500, 502, 503, 504],
                        method_whitelist=frozenset(['GET', 'POST']),
                        raise_on_status=False)
        self.session.mount('https://', HTTPAdapter(max_retries=retries))

Comments

0

I cam across this posting while learning the python API for google compute requests and found it to be accurate but old; much of the code has been integrated into the google libraries now. One way to get/use a token:

auth_req = google.auth.transport.requests.Request()
creds.refresh(auth_req)
print(f'token: {creds.token} : {creds.valid} {creds.expiry}')

# read all disks under project/zone
url='https://compute.googleapis.com/compute/v1/projects/prog-name/zones/zone-name/disks'
headers_api = {'Authorization': 'Bearer ' + creds.token}
resp = requests.get(url=url, headers=headers_api)

for disk in resp.json()['items']:
    print(f"{disk['name']}: {disk['sizeGb']}")

This is further consolidated in the google.cloud.compute_v1 API:

project='prog-name'
zone='zone-name'

# get a context for the API client
client = compute_v1.InstancesClient()
# get the VMs in the project/zone 
clist = client.list(project=project, zone=zone)

# print each VM
for vm in clist.pages:
    print("VM: {}".format(vm))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.