Connect to AWS IoT Core MQTT from iOS
Test AWS IoT Core from your iPhone: import a device certificate and key, set the x-amzn-mqtt-ca ALPN protocol, and connect over mutual TLS to publish and subscribe.
May 26, 2026
AWS IoT Core and Mutual TLS
AWS IoT Core requires every connecting device to authenticate with a client certificate signed by AWS — not just a username and password. This design, known as mutual TLS (mTLS), means the broker verifies the client and the client verifies the broker in the same TLS handshake. There is no option to disable it on the standard endpoints.
For embedded firmware running on a microcontroller, managing those certificates is handled by the SDK. On a laptop you might load them into Mosquitto or the AWS IoT Device Client. On an iPhone, you need an MQTT client that understands PEM certificates, stores secrets in the iOS Keychain, and lets you tune the ALPN extension — which is exactly what MQTT Commander provides.
This guide walks through everything from grabbing your endpoint in the AWS console to publishing your first test message from your phone.
What You Need Before You Start
- ATS endpoint — In the AWS IoT console, open Settings and copy the Device data endpoint. It looks like
<prefix>-ats.iot.<region>.amazonaws.com. The-atssuffix matters; the legacy VeriSign endpoint is being retired. - Device certificate (
certificate.pem.crt) — Created when you registered a Thing or used the IoT console’s one-click certificate wizard. - Private key (
private.pem.key) — Generated at the same time as the certificate. AWS does not store the private key server-side; if you lost it, revoke the certificate and create a new one. - Root CA (optional but recommended) — Amazon’s ATS root CA is already trusted by iOS, but importing it explicitly lets MQTT Commander validate the full chain for you.
- IoT policy — A policy attached to the certificate that grants
iot:Connect,iot:Publish, andiot:Subscribefor the topics you intend to use.
A minimal policy for testing looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Connect",
"iot:Publish",
"iot:Subscribe",
"iot:Receive"
],
"Resource": "arn:aws:iot:<region>:<account-id>:*"
}
]
}
Scope it down to specific topic ARNs before using it in production.
Importing the Certificate and Key into MQTT Commander
MQTT Commander’s Certificate Manager stores credentials in the iOS Keychain — they never leave the device and are not synced to iCloud or any external server.
- Transfer
certificate.pem.crtandprivate.pem.keyto your iPhone. AirDrop, the Files app, or a share sheet from Safari all work. - In MQTT Commander, open the Connections tab and tap + to create a new connection, or open an existing one and go to TLS Settings.
- Tap Certificate Manager → Import Certificate.
- Choose PEM mode. Paste or load the PEM content for:
- CA Certificate — the Amazon root CA (optional if you rely on system trust).
- Client Certificate —
certificate.pem.crt. - Private Key —
private.pem.key. If you exported from ACM with a passphrase, enter it in the Key Passphrase field.
- Tap Validate. The Certificate Wizard checks the chain, expiry, SAN/CN, and SHA-256 fingerprints and reports any issues before you ever attempt a connection.
If you have a .p12 / .pfx bundle (exported from a keystore or OpenSSL), MQTT Commander accepts that format too — just switch to PKCS#12 mode and supply the bundle password.
Port 8883 vs. Port 443 and the ALPN Extension
AWS IoT Core listens for MQTT over two ports:
| Port | Protocol | ALPN required |
|---|---|---|
8883 | MQTT over TLS | None (or mqtt) |
443 | MQTT over TLS via ALPN | x-amzn-mqtt-ca |
Port 8883 is the traditional MQTT/TLS port. Many corporate firewalls block it. Port 443 is always open for HTTPS traffic, which is why AWS supports MQTT on it via the ALPN extension — the client advertises x-amzn-mqtt-ca in the TLS ClientHello, and the server hands off to the MQTT broker instead of an HTTPS handler.
To configure this in MQTT Commander:
- Host:
<prefix>-ats.iot.<region>.amazonaws.com - Port:
443(or8883) - TLS: enabled, with the certificate profile you just imported
- ALPN: in the Advanced TLS section, add
x-amzn-mqtt-cato the ALPN protocol list - SNI: leave it set to the hostname; AWS requires SNI to route the connection correctly
If you are on a network that blocks 8883 and you forget to set the ALPN on port 443, the TLS handshake will complete but AWS will immediately close the connection — the Connection Doctor surfaces this as a TLS-layer drop rather than a silent timeout.
Connecting and Running Your First Test
With the certificate imported and ALPN configured, tap Connect. MQTT Commander runs through its staged diagnostics: DNS resolution → TCP handshake → TLS handshake (including mTLS certificate exchange) → MQTT CONNECT → CONNACK.
A successful CONNACK with return code 0 (Connection Accepted) means AWS authenticated your device certificate, matched it to an active certificate record, and found a policy that allows iot:Connect for your client ID.
Subscribe first, then publish:
- Tap Subscribe and enter a topic your policy allows, for example
devices/my-phone/status. - Tap Publish, set the same topic, and send a JSON payload:
{
"temperature": 22.5,
"unit": "C",
"timestamp": 1716768000
}
The message should appear in the subscriber pane immediately. You can also open the AWS IoT console’s MQTT test client on your laptop and subscribe to the same topic to confirm messages are flowing end-to-end.
Common Errors and How Connection Doctor Surfaces Them
Policy Denies the Action
CONNACK return code 5 (Not Authorized) or, in MQTT 5.0, reason code 0x87 (Not Authorized). The certificate authenticated successfully but the attached policy does not grant the required action (iot:Connect, iot:Publish, etc.) for the resource ARN. Check the policy in the AWS console and confirm the certificate is Active and the policy is attached to the certificate (not just to the Thing).
Wrong ALPN on Port 443
If you connect on port 443 without x-amzn-mqtt-ca in the ALPN list, the AWS load balancer treats it as HTTPS and returns an HTTP 400 or closes the socket. Connection Doctor flags this at the TLS stage as an unexpected socket close, not at the MQTT stage, which narrows the search immediately.
Hostname Mismatch / SNI Missing
Using an IP address instead of the ATS hostname, or disabling SNI, causes the TLS handshake to fail with a certificate verification error. AWS IoT Core presents a certificate for the hostname, so SNI must carry the correct hostname. MQTT Commander enables SNI by default and lets you override it only when you have a deliberate reason (for example, testing behind a reverse proxy).
Expired or Revoked Certificate
If the device certificate has been deactivated or revoked in the AWS console, the CONNACK will return Not Authorized. The Certificate Wizard will warn you at import time if the certificate’s notAfter date has already passed, saving a round-trip to AWS before you even connect.
Testing Across Environments
One of the practical advantages of testing AWS IoT from an iPhone is that you can validate connectivity from a cellular network — no corporate VPN, no local Wi-Fi that might have special routing — giving you a clean signal that your policy and endpoint are correctly configured for real devices in the field.
For a deeper look at TLS certificate formats, chain validation, and how to debug mTLS handshake failures in general, see the companion post MQTT TLS and mTLS Debugging. If you are new to running MQTT from a phone, MQTT on iPhone covers the basics of setting up your first connection.
MQTT Commander is a one-time $2.99 purchase for iOS and iPadOS 15+, with no subscription and no data leaving your device beyond anonymous crash diagnostics.