3

I'm using the standard oauth2 web flow example from requests-oauthlib to get a token from QuickBooks Online's API but whilst I've successfully redirected to the QBO site, authorised and has a code returned to request a token I am getting a:

oauthlib.oauth2.rfc6749.errors.InvalidClientError

Error when I am actually making the token request. Having googled a lot it seems like I am not authorising correctly. QBO says the actual request might look like the following:

POST https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer HTTP/1.1
Accept: application/json
Authorization: Basic UTM0dVBvRDIwanp2OUdxNXE1dmlMemppcTlwM1d2
    NzRUdDNReGkwZVNTTDhFRWwxb0g6VEh0WEJlR3dheEtZSlVNaFhzeGxma1l
    XaFg3ZlFlRzFtN2szTFRwbw==
Content-Type: application/x-www-form-urlencoded
Host: oauth.platform.intuit.com
Body: grant_type=authorization_code&
code=L3114709614564VSU8JSEiPkXx1xhV8D9mv4xbv6sZJycibMUI&
redirect_uri=https://www.mydemoapp.com/oauth-redirect

And that I need to generate the authorization headers like this:

"Basic " + base64encode(client_id + ":" + client_secret)

I've created the above like this:

auth_code = client_id + ":" + client_secret
auth_code = base64.b64encode(bytes(auth_code, 'utf-8'))
auth_code = auth_code.decode('utf-8')

But passing this through in the token code like:

token = qbo.fetch_token(token_url, code=code, authorization_response=redirect_uri, headers={'Authorization' : auth_code})

Resulted in the InvalidClientError message. I feel like I'm really close but failing at the final oauth2 hurdle but can someone help me authorise for the token please?

Many thanks, John

------ edit 1 -----

Thanks stovfl, that's super helpful and I've tried a couple of new things now based on your advice. I've just updated the code so that it reads like this:

headers = {'Accept':'application/json'}
headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
auth = HTTPBasicAuth(client_id, client_secret)
body = 'grant_type=authorization_code&code=' + code + '&redirect_uri=' + redirect_uri_token
token = qbo.fetch_token(token_url, auth=auth, body=body, headers=headers)

That produced another error:

ValueError: Please supply either code or authorization_response parameters.

Checking the actual oauth library code it's mandatory to give the code/authresponse so I updated again to get the code from the callback and use it in my fetch_token request:

all_args = request.args.to_dict()
code = all_args['code']
headers = {'Accept':'application/json'}
headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
auth = HTTPBasicAuth(client_id, client_secret)
body = 'grant_type=authorization_code&code=' + code + '&redirect_uri=' + redirect_uri_token
token = qbo.fetch_token(token_url, code=code, auth=auth, body=body, headers=headers)

I've also tried removing the code and just having in the main call so the body looks like this:

body = 'grant_type=authorization_code' + '&redirect_uri=' + redirect_uri_token

But either way it now goes back to the previous error of:

oauthlib.oauth2.rfc6749.errors.InvalidClientError: (invalid_client)

I'm not sure where to go from here.

1
  • 1
    I found I needed to include a scope parameter in the body. Commented Sep 11, 2022 at 4:31

1 Answer 1

3

Question: QuickBooks intuit Developer: Exchange authorization code for access token, using OAut2.0.

According to the given Request Example, you should do:

  1. LINE: POST https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer HTTP/1.1

    POST to https://oauth.plat... HTTP Version 1.1, Defaults using OAuth2.fetch_token(....

    url_endpoint = 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
    
  2. LINE: Accept: application/json

    You have to accept application/json, OAuth2.fetch_token(... accepts anything by default. Nothing to do, but for completeness you can define it as follows:

    headers = {'Accept':'application/json'}
    
  3. LINE: Authorization: Basic a2V5OnNlY3JldA==

    It's required that you pass auth credentials in a Basic Auth header

    from requests.auth import HTTPBasicAuth
    auth = HTTPBasicAuth(client_id, client_secret)
    
  4. LINE: Content-Type: application/x-www-form-urlencoded

    The body Data has to passed form-urlencoded.

    headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
    
  5. LINE: Host: oauth.platform.intuit.com

    User specific, nothing to do

  6. LINE: Body: grant_type=authorization_code&code=L311...&redirect_uri=https://www.mydemoapp.com/oauth-redirect

    Data placement in body.

    body = 'grant_type=authorization_code&code=L311...&redirect_uri=https://www.mydemoapp.com/oauth-redirect'
    
  7. Exchange authorization code for access token

    token = qbo.fetch_token(url_endpoint, auth=auth, body=body, headers=headers)
    

Note: Cant't verify with QuickBooks intuit Developer but requests give me the following Request Message:

Request Message:

headers:
    Accept: application/json
    Accept-Encoding:    gzip, deflate
    Content-Length: 139
    User-Agent: python-requests/2.11.1
    Authorization:  Basic a2V5OnNlY3JldA==
    Host:   ... omited, because user specific
    Content-Type:   application/x-www-form-urlencoded
form:
    grant_type: authorization_code
    code:   L3114709614564VSU8JSEiPkXx1xhV8D9mv4xbv6sZJycibMUI
    redirect_uri:   https://www.mydemoapp.com/oauth-redirect

Tested with Python:3.4.2 - requests:2.11.1

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

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.