TLS and CA pinning
TLS and CA pinning
On the home network the gateway serves HTTPS (TLS 1.3 only) with a server certificate signed by its own certificate authority, made once on the gateway (valid about 20 years; its private key never leaves the gateway). The server certificate names igh-<serial>.local, igh-<serial> and the gateway's current LAN addresses, lasts about a year and is renewed by itself. Clients trust only that CA for that gateway: pin it.
Never turn off certificate verification (curl -k, verify=False, rejectUnauthorized: false, InsecureSkipVerify). There is no plain-HTTP fallback.
Getting the CA. Either:
- from the integration's page in the app: the CA's fingerprint and a download of its file; or
GET /v1/gateway/tlsthroughhttps://api.igh.app(publicly trusted TLS):{ ca, fingerprint, algorithm: "SHA-256", createdAt, house }.cais the PEM certificate;fingerprintis the SHA-256 of its DER bytes, upper-case hex pairs joined by colons.
Check that the fingerprint you computed from ca equals fingerprint, store the PEM next to the credential, and use it as the only trust anchor for that gateway.
On a certificate error (unknown issuer, wrong name): fetch the CA again the same way. If its fingerprint differs from the one you pinned, tell the user before trusting it: an administrator may have regenerated the CA on the integration's page (integrations.record), or something is impersonating the gateway. Never accept a changed CA silently. A name mismatch after the gateway moved to another address heals by itself within minutes (the certificate is reissued); use igh-<serial>.local meanwhile.
Pinning recipes
Fetch the CA once (and again after a certificate error):
curl -sS https://api.igh.app/v1/gateway/tls -H "Authorization: Bearer $IGH_KEY" | jq -r .ca > igh-ca.pem
openssl x509 -in igh-ca.pem -noout -fingerprint -sha256 # compare with the answer's "fingerprint"
curl
curl -sS --cacert igh-ca.pem https://igh-<serial>.local:8490/v1/state -H "Authorization: Bearer $IGH_KEY"
Python (requests)
import requests
r = requests.get("https://igh-<serial>.local:8490/v1/state",
headers={"Authorization": f"Bearer {key}"},
verify="igh-ca.pem") # the gateway's CA only; never verify=False
r.raise_for_status()
Node.js
import { readFileSync } from "node:fs";
import { request } from "node:https";
const ca = readFileSync("igh-ca.pem");
request("https://igh-<serial>.local:8490/v1/state", { ca, headers: { authorization: `Bearer ${key}` } }, (res) => res.pipe(process.stdout)).end();
Go
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caPEM)
client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{RootCAs: pool, MinVersion: tls.VersionTLS13}}}
WebSocket clients take the same CA (ca in Node's ws, ssl=ssl.create_default_context(cafile="igh-ca.pem") in Python's websockets).
Examples
Get the gateway's CA to pin it.
GET /v1/gateway/tls
Answer 200:
{
"house": "Cohen Home",
"ca": "-----BEGIN CERTIFICATE-----\nMIIB…\n-----END CERTIFICATE-----\n",
"fingerprint": "3A:5F:…:C2",
"algorithm": "SHA-256",
"createdAt": 1760000000000
}
IGH home API 1.1.0. Generated from the doc source; do not edit.