ESP8266 HTTPS POST assistance

Hi

I am wishing retrieve some information from my Tado internet thermostat using an ESP8266 and have found this curl command detailed by chap called Terrence Eden (thank you) on his Web Blog:

curl -s "https://auth.tado.com/oauth/token" -d client_id=tado-web-app -d grant_type=password -d scope=home.user -d username="you@example.com" -d password="Password123" -d client_secret=wZa

Being on Windows I have executed this curl using the online "reqbin" service and it returns the information that it promises.

I have tried to convert this curl command into code that will run on the ESP, but it fails as described below:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecureBearSSL.h>
#include <ESP8266HTTPClient.h>

.
.
.

String Host = "https://auth.tado.com/oauth/token";
String PostData = "client_id=tado-web-app&grant_type=password&scope=home.user&username=you@example.com&password=Password123&client_secret=wZa";
.
.
.
void loop() {
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
  if (client) {
    // set secure client without certificate
    client->setInsecure();

    //create an HTTPClient instance
    HTTPClient https;

    // Set the content type."
    https.addHeader("Content-Type", "application/x-www-form-urlencoded");

    //Start HTTPS comms"
    Serial.println("Start HTTPS comms");

    if (https.begin(*client, Host)) { 

      Serial.println("In https.begin");

      // Execute the POST
      int httpCode = https.POST(PostData);

      if (httpCode > 0) {
        // HTTP response
        Serial.printf("HTTPS respnse %d\n", httpCode);

        // Payload
        String payload = https.getString();
        Serial.println(payload);
      }
    }
    https.end();
  } else {
    Serial.println("Connection failure");
  }

  Serial.println();
  Serial.println("Pausing for a long time.");
  delay(1000000);
}

The ouput from this is:

Start HTTPS comms
In https.begin
HTTPS respnse 401
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}

Pausing for a long time.

Can anyone help me understand what I am doing wrong please?

This is my first attempt at HTTP/HTTPS communication. So please treat me as a complete beginner.

Thank you.

Two related, and often-confused concepts

  • authentication: "I can prove who am I", sometimes abbreviated authN
  • authorization: "Now that I have proved who am I, what am I allowed to do", authZ

401 Unauthorized is a standard HTTP response code, and the error message is clear: you haven't proved who you are, therefore you aren't allowed to do anything.

A related status code is 403 Forbidden: the server recognizes you, and because of that, knows you aren't allowed to do that.

401 means you are missing authN credentials, often a user name and password; or they are invalid. You have (redacted) credentials in your PostData, so the likely problem is that the addHeader for the Content-Type should be after the begin, before the POST; not before the begin.

If that works, you get a token -- usually a (long) string of gibberish -- in return. Unfortunately, it looks like the HTTPClient only supports the Basic authorization scheme. OAuth tokens use Bearer authorization, so you'll need to set the header manually

String token = "gibberish-from-previous-call";
// ...
httpClient.addHeader("Authorization", "Bearer " + token);

I have been checking, double checking, changing the format of the PostData, changing the structure to json, etc, for two evenings now and getting so frustrated.

Now after a simple request for assistance , you pointed out the move of a line of wrongly placed code and it works!

kenb4 - Thank you so much.

I used the ESP8266 on my mailbox notifier feeding into the Pushover app server. Perhaps my code will be of some use.

https://github.com/gbhug5a/Mailbox-Notifier

That looks very useful. Especially as I am bit of a novice with HTTP communication.
Cheers.