python-requestsmicropython

Why do I get a "Invalid grant_type" error when I want to refresh the access token? - Netatmo API


I want to refresh the access token for the Netatmo API. I tried different things but I get every time the same error. I use MicroPython and the urequests lib for the requests.

The error is:

Status Code: 400

{"error":"invalid_request","error_description":"Invalid grant_type parameter or parameter missing"}

At first I tried, as it works for me in normal Python, to make a request post.

payload = {
    'grant_type': 'refresh_token',
    'refresh_token': 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'client_id': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'client_secret': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
}

response = requests.post("https://api.netatmo.com/oauth2/token", 
   data=payload)

The result was: TypeError: object with buffer protocol required

I found out that urequests can not handle it, because it does not know which protocol it has to use.

Next I converted it to a bytearry. Then I don't get the type error, but I get the error invalid_request

{"error":"invalid_request","error_description":"Invalid grant_type parameter or parameter missing"}

After that, I tried to set the headers, but I got the same error as without headers.

payload = {
        'grant_type': 'refresh_token',
        'refresh_token': 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
        'client_id': 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
        'client_secret': 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
    }

headers = {'Content-Type': 'application/x-www-form-urlencoded',}

payload_json = json.dumps(payload)
payload_bytes = bytearray(payload_json, 'utf-8')

response = requests.post('https://api.netatmo.com/oauth2/token', data=payload_bytes, headers=headers)

At the end I even tried to build the URL by hand, but I still get the invalid request error. This is the URL I tried to build:

https://api.netatmo.com/oauth2/token?&grant_type=refresh_token&refresh_token=XXXXXXXXXXXXXXXXXXXXXXXXXX&client_id=XXXXXXXXXXXXXXXXXXXXXXXXXX&client_secret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Can please somebody help me?


Solution

  • As assumed is the problem, that the format is wrong and the urequests can not read the format. After a long conversation with ChatGPT is the solution to encode the URL. The method ChatGPT gave me was:

    def urlencode(params):
        encoded_str = ''
        for key, value in params.items():
            encoded_str += '{}={}&'.format(key, value)
        return encoded_str[:-1]
    

    It works for me perfectly. So here is the complete code how it works for me:

    import urequests as requests
    
    def urlencode(params):
        encoded_str = ''
        for key, value in params.items():
            encoded_str += '{}={}&'.format(key, value)
        return encoded_str[:-1]
    
    payload = {
            'grant_type': 'refresh_token',
            'refresh_token': 'XXXXXXXXXXXXXXXXXXXXXXXX',
            'client_id': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
            'client_secret': 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
        }
    
    payload_encoded = urlencode(payload)
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    
    response = requests.post('https://api.netatmo.com/oauth2/token', data=payload_encoded, headers=headers)
    
    print(response.status_code)
    print(response.text)