0

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.

Diego-MX
  • 2,279
  • 2
  • 20
  • 35

0 Answers0