I come here for help after being stuck a few hours creating an OAuth2
Async
httpx
client.
It's one of those situations that feels so close, and still doesn't come through in the end.
I'm using this oauth2 session/client documentation:
What I need:
- Creating an
oauth2_async_client
with authentication implemented at the creation -hopefully-.
The flow isn't that much different than what is described in the documentation. - Understanding the usage of
fetch_token
in the client.
About the flow:
I have two sets of credentials: a service principal (id, secret), and (user, password) that are called inside
data
.The Postman Authentication request looks like this:
// Postman call
auth_enc = btoa(sp_key+":"+sp_secret)
var a_request = {
url : auth_login,
method : 'POST',
header : { "Authorization": "Basic "+auth_enc,
"Content-Type":"application/x-www-form-urlencoded"},
body: {
mode: "urlencoded",
urlencoded : [
{ key: 'username' , value: user },
{ key: 'password' , value: pass },
{ key: 'grant_type', value:'password'},
] } }
pm.sendRequest(a_request, (error, response) => {
if (error === null) {
pm.environment.set("ERP_TOKEN", response.json()["access_token"])
};
} );
What I tried:
class ERPClientX(OauthAsyncClient):
def __init__(self, config, **kwargs):
self.config = config
clienters = {
'client_id' : config['client_id'],
'client_secret': config['client_secret'],
'token_endpoint_auth_method': 'client_secret_basic'}
authers = {
'url' : self.config['auth-url'],
'data' : self.config['auth-data']), # Keys: {grant_type, username, password}
'headers': {'Content-Type': "application/x-www-form-urlencoded"}}
super().__init__(**clienters, **kwargs)
self.create_authorization_url(**authers)
self.base_url = self.config['base-url']
self.headers.update(self.std_headers)
std_headers = { # For the general request, not auth.
'Accept-Encoding' : 'gzip, deflate',
'Content-Type' : 'application/json',
'Accept' : 'application/json',
'Format' : 'json'}
async def inside_call(self, call_params):
sub_url = f"/call-me-maybe/{params['number']}/"
the_resp = await self.get(sub_url) # prepended by base_url defined above.
# Do something with result.
results_ls = the_resp.json()['d']['results']
for each_result in results_ls:
each_result.pop('__metadata')
results_df = (pd.DataFrame(results_ls)
.assign(ts_call=dt.now().strftime("%Y-%m-%d %H:%M:%S")))
return results_df
The error I get:
TypeError: 'str' object cannot be interpreted as an integer
...
307
308 super().__init__(**clienters, **kwargs)
--> 309 uri, _ = self.create_authorization_url(**authers)
310
When I didn't include the data
and headers
parameters in create_authorization_url
-authers
dict, I got another error:
<MissingTokenError \"missing_token\"
.
The documentation has several examples of using fetch_token
but haven't been able to get my head around it.
Thank you for your help.