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.