Making an HTTPS POST call to Amazon AWS api gateway using Arduino Uno R4 WiFi

Dear Arduino community,

I require to make an HTTPS POST call to Amazon AWS api gateway using Arduino Uno R4 WiFi.
My code is this:

#define SECRET_SSID "xxxxx"
#define SECRET_PASS "xxxxxx"

#include "WiFiS3.h"
#include <ArduinoHttpClient.h>

// credentials
const char* ssid = SECRET_SSID;
const char* pass = SECRET_PASS;

// endpoint
const char* airQualityApi = "xxxxxxxx.execute-api.ca-central-1.amazonaws.com";
int port = 443; 

WiFiSSLClient client; 

const char* root_ca = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIF+jCCBOKgAwIBAgIQDx2LdHYjwUKACiThmfYnYzANBgkqhkiG9w0BAQsFADA8\n" \
"MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g\n" \
"UlNBIDIwNDggTTAzMB4XDTI0MDUwMjAwMDAwMFoXDTI1MDUzMTIzNTk1OVowMzEx\n" \
"MC8GA1UEAwwoKi5leGVjdXRlLWFwaS5jYS1jZW50cmFsLTEuYW1hem9uYXdzLmNv\n" \
"bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMvDfJzSmdOtLrssK3e6\n" \
"u9cLM8HIe033DCaWhwh4b9PQk6U8lPdBpdhcYawaK2VBL0j7xkgsIBlAhPOEpYcL\n" \
"Zjc78U7qwz52uWf1T3evtJnSzy9lMlw8MNPBEuglIb0+p19gWb5lrvLqmRlQQCCA\n" \
"h6lR9Bu4pjnCoM+ddQ7yrpU9KdHMOtIFr7GVij08ZdGbCA60T4OOoRCrSLlektaU\n" \
"GrRaRFRNa36ttPGR6wG7LYl9mIxaMFZXzKASPII+G0lAs4IgYvzBGwgipi6t21oi\n" \
"199Hg2p5+KF6GqMo3/bgdAFEa3qpEYLDKfdtR7V/+O2xzO8pggQyrF3tLR7nO8NV\n" \
"wg0CAwEAAaOCAv8wggL7MB8GA1UdIwQYMBaAFFXZGF/SHMwB4Vi0vqvZVUIB1y4C\n" \
"MB0GA1UdDgQWBBSrtytghbX44SulKDRDLZ0i/WELNzAzBgNVHREELDAqgigqLmV4\n" \
"ZWN1dGUtYXBpLmNhLWNlbnRyYWwtMS5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow\n" \
"CAYGZ4EMAQIBMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI\n" \
"KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMy5hbWF6\n" \
"b250cnVzdC5jb20vcjJtMDMuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw\n" \
"AYYhaHR0cDovL29jc3AucjJtMDMuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC\n" \
"hipodHRwOi8vY3J0LnIybTAzLmFtYXpvbnRydXN0LmNvbS9yMm0wMy5jZXIwDAYD\n" \
"VR0TAQH/BAIwADCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHUATnWjJ1yaEMM4\n" \
"W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGPNqQ21wAABAMARjBEAiAu9BohKmLQ\n" \
"uS9lIf61W8mfDg6LzawjeZNEroZbUQTD/QIgbZH74UzyqwI5C5JjG91A2pHuAcnX\n" \
"omDi8C0eT77zdBgAdgB9WR4S4XgqexxhZ3xe/fjQh1wUoE6VnrkDL9kOjC55uAAA\n" \
"AY82pDb7AAAEAwBHMEUCIQDjjqm95PqYCX4svyd0e7eXsDqDdhDhJmKrBIUt7RVw\n" \
"lAIgHFSyL/R0pV27dVocf/+HWLgd5rl1chtNhofBR7HLH28AdQDm0jFjQHeMwRBB\n" \
"Btdxuc7B0ksdczxczdczMh39HjeOUAAAAY82pDcNAAAEAwBGMEQCID7MWq15los6\n" \
"wkkAKdqE0CwgLEtTmeqFK6zfWpAO2xOgAiAqDzx4OZi3pmNmr+4jwaJCjv2L6+3i\n" \
"2G0bwpddtWXzqzANBgkqhkiG9w0BAQsFAAOCAQEAjzY2uugyGnEGr+Xlg60Uxb6U\n" \
"NtvE+VyU6aF4dA2rwXXsHvc+vjJ0/YJ7oNOBSHWijnbi9IoNhSeintLYslujMGGB\n" \
"gPDfmVFDoTD5rX39uo1AiFBH2XvnlO3P2BMNxbFfKYyAlANRvdRyitJTF0VdFrqS\n" \
"/knv52gFaTrPCELSL9NFGIgTgfxlo2p+P1w0mooQqQt1o9njv56MdoGuoE9jSq57\n" \
"uqNbPlMX9zgJtAM3U+GlN1/RD7uncM1tWgkX6U8Xr5n0pI4zWGRkkJWt4O/5kSc5\n" \
"b+UT9lWp9/CW5KaMCOn48O40FZY+x/DqKRsRtiWiFgW4mtohzlsANO53VrOCdQ==\n" \
"-----END CERTIFICATE-----\n";

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }

  // Connect to WiFi
  WiFi.begin(ssid, pass);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // root certificate
  client.setCACert(root_ca);

  // fixed value data to API
  sendData(airQualityApi, "/co2INSERT_stage/co2INSERT_REST", "airQuality", 123.45);
}

void loop() {
  // Intentional
}

void sendData(const char* server, const char* resourcePath, const char* sensorType, float value) {
  Serial.print("Connecting to server: ");
  Serial.println(server);

  // connect to the server
  if (!client.connect(server, port)) {
    Serial.println("Connection failed!");
    return;
  }

  // JSON payload with fixed value
  String jsonData = "{\"sensorValue\":" + String(value, 2) + "}";

 
  Serial.print("Sending JSON data: ");
  Serial.println(jsonData);

  client.print(String("POST ") + resourcePath + " HTTP/1.1\r\n" +
               "Host: " + server + "\r\n" +
               "User-Agent: Arduino/1.0\r\n" +
               "Content-Type: application/json\r\n" +
               "Content-Length: " + String(jsonData.length()) + "\r\n" +
               "Connection: close\r\n\r\n" +
               jsonData);

  int timeout = millis() + 5000;
  while (client.available() == 0) {
    if (timeout - millis() < 0) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }

  client.stop();
}

I can confirm that my Arduino gets connected to WiFi (have checked with Google to get its Html, which works).
I can also confirm that the API endpoint is accessible, tried it with Postman and works flawlessly.

However using the Arduino it does not work.
Could you please guide me in this?
I have obfuscated the root cert and removed the WiFi info for confidentiality reasons.

Many thanks in advance.

Kind Regards,
Shizar

At what point does it fail? Is there an error message or other output?

These certificates use public key cryptography, using key pairs with a public half and private half. While the private keys should never ever be leaked, It is expected that the public keys are known, and are not a secret.

Despite obfuscation, the cert in your code looks like a leaf cert, not a root cert

Issuer: C = US, O = Amazon, CN = Amazon RSA 2048 M03
Validity
    Not Before: May  2 00:00:00 2024 GMT
    Not After : May 31 23:59:59 2025 GMT
Subject: CN = *.execute-api.ca-central-1.amazonaws.com

This is a short-lived cert for the AWS API gateway servers in that specific region. The SSL client cannot verify an SSL connection with the same cert that is presented by the web site.

The UNO R4 WiFi has a root cert bundle in its firmware, including the four Amazon roots like this "self-issued" one

Issuer: C = US, O = Amazon, CN = Amazon Root CA 1
Validity
    Not Before: May 26 00:00:00 2015 GMT
    Not After : Jan 17 00:00:00 2038 GMT
Subject: C = US, O = Amazon, CN = Amazon Root CA 1

(Make sure your firmware is up-to-date.) Use setCACert only if you need an obscure/custom one. Try commenting out that statement.

Hi @kenb4 ,

The certificate solved the issue.
I wish I could somehow express my gratitude for your help.

Please do continue helping others, you have no idea how happy I am now :smiley:

Looking forward to your guidance.

Kind Regards,