Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid InValidClientError with requests-oauthlib token fetching?

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.

like image 203
Johnny John Boy Avatar asked May 28 '26 11:05

Johnny John Boy


1 Answers

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

like image 93
stovfl Avatar answered Jun 01 '26 15:06

stovfl