AWS IoT lifecycle event messages

Originally posted on 2023-12-14

I didn’t find any place with decent example JSON for AWS IoT lifecycle events so I decided to post some myself. If you want to know interesting trivia about lifecycle events scroll to the bottom!

What are lifecycle events?

AWS IoT lifecycle events tell you when an MQTT client connects or disconnects. This client can be “real” MQTT or can be MQTT over WebSockets. However, messages sent with the iotdata.Publish API will not create lifecycle events since they’re injected into the broker by AWS and don’t involve a normal connection/disconnection cycle.

Where do lifecycle events go?

Lifecycle events are on two topic hierarchies:

  • $aws/events/presence/connected/#
  • $aws/events/presence/disconnected/#

It’s important to note that subscribing a client to the MQTT wildcard # will NOT include messages from these special topic hierarchies! You need to subscribe to them explicitly to get messages from them in both MQTT clients and IoT rules.

What do the lifecycle event topics look like?

Both connection and disconnection lifecycle events put the client’s client ID value in the topic like this:

$aws/events/presence/connected/CLIENT_ID
Connection lifecycle event topic
$aws/events/presence/disconnected/CLIENT_ID
Disconnection lifecycle event topic

What do the lifecycle event payloads look like?

Connections

A connection payload can come in multiple varieties. Connections from the AWS IoT MQTT test client console will have the principalIdentifier field set to an IAM user’s (or SSO user’s) access key ID along with usually an identifier like their e-mail address like this:

{
    "clientId": "iotconsole-4b0d04fe-a776-472a-9121-f7fe39ab680f",
    "timestamp": 1702562499818,
    "eventType": "connected",
    "sessionIdentifier": "8b76421b-2b19-41a1-9115-cb5b1d91c648",
    "principalIdentifier": "AROASTLVWKQ4VKIMFNOIF:tim@mattison.org",
    "ipAddress": "8.8.42.11",
    "versionNumber": 0
}
Connection to AWS IoT via the AWS IoT MQTT test client from an IAM/SSO user

When a client connects with a client certificate the principalIdentifier is the certificate’s hash (also the AWS IoT client certificate ID) and the connection message will look like this:

{
    "clientId": "test",
    "timestamp": 1702566391861,
    "eventType": "connected",
    "sessionIdentifier": "7e229bae-555c-4ace-a308-df2c229d27d0",
    "principalIdentifier": "226c64225fce225672257c31e2cb6d3ad21ca514af690bc5cb44f5f58c2222",
    "ipAddress": "8.8.42.11",
    "versionNumber": 96
}
Connection to AWS IoT via an MQTT client with certificate based authentication

Disconnections

When a client disconnects it looks very similar to the connection event but has a few added fields:

  • clientInitiatedDisconnect - a boolean that tells you whether the client wanted to disconnect or was disconnected due to an error/issue
  • disconnectReason - why the client disconnected, some examples:

A sample payload from a client that closed its connection without disconnecting gracefully:

{
    "clientId": "test",
    "timestamp": 1702567748504,
    "eventType": "disconnected",
    "clientInitiatedDisconnect": false,
    "sessionIdentifier": "2116bc07-0c75-4e3a-a89a-61e0c786ba",
    "principalIdentifier": "226c64225fce225672257c31e2cb6d3ad21ca514af690bc5cb44f5f58c2222",
    "disconnectReason": "CONNECTION_LOST",
    "versionNumber": 131
}
A non-graceful lost connection from a client authenticated with a certificate

Here’s one from a client disconnecting gracefully:

{
    "clientId": "test",
    "timestamp": 1702568225845,
    "eventType": "disconnected",
    "clientInitiatedDisconnect": true,
    "sessionIdentifier": "c69eff23-69c3-4c07-9927-c8278833f4",
    "principalIdentifier": "AROASTLVWKQ4VKIMFNOIF:tim@mattison.org",
    "disconnectReason": "CLIENT_INITIATED_DISCONNECT",
    "versionNumber": 139
}
A graceful disconnection from an IAM/SSO user

Trivia

Hidden clients

Clients that have a # or + character will not produce lifecycle events! If possible it’s best to prevent clients with client IDs like this from connecting.

Version numbers

The version number helps your applications figure out the order of events since events may show up both out of order and duplicated.

The version number for a disconnect corresponds to the version number for that client’s original connection message.

Duplicate client IDs

Two clients cannot have the same client ID. If a new client connects with a client ID that matches an existing client the existing client is knocked offline.

This can be useful if you need to remove the permissions from a malicious client and disconnect it immediately. Disable their access and then reconnect with their client ID and they’re gone.