I'm trying to connect a web client to AWS IoT Core using JavaScript over WebSocket, authenticated via Amazon Cognito Identity Pool.
The connection works (confirmed via logs), and the subscription to the topic is successful, but I do not receive any messages, even though messages are actively published (verified using AWS Test Client).
I have granted permissions to the unauthenticated role used by Cognito and also attached the policy to the certificate used by the device.
IAM Policy used:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Connect",
"iot:Subscribe",
"iot:Receive",
"iot:Publish"
],
"Resource": "*"
}
]
}
JavaScript code:
// --- Configuration ---
const AWS_REGION = '';
const COGNITO_IDENTITY_POOL_ID = '';
const IOT_CORE_ENDPOINT = '';
const MQTT_TOPIC = '';
// --- DOM Elements ---
const connectionStatusElement = document.getElementById('connection-status');
const iotDataElement = document.getElementById('iot-data');
const reconnectButton = document.getElementById('reconnect-button');
let connection; // Declare connection globally to manage its state
// --- Function to get AWS Credentials from Cognito ---
async function getAWSCredentials() {
AWS.config.region = AWS_REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: COGNITO_IDENTITY_POOL_ID
});
try {
await AWS.config.credentials.getPromise();
console.log('Successfully got AWS credentials from Cognito.');
return {
accessKeyId: AWS.config.credentials.accessKeyId,
secretAccessKey: AWS.config.credentials.secretAccessKey,
sessionToken: AWS.config.credentials.sessionToken
};
} catch (error) {
console.error('Error getting AWS credentials:', error);
throw error; // Propagate the error
}
}
// --- Function to Connect to AWS IoT Core and Subscribe ---
async function connectAndSubscribe() {
connectionStatusElement.textContent = 'Connecting...';
reconnectButton.style.display = 'none';
try {
const credentials = await getAWSCredentials();
const clientID = `web_client_${Math.random().toString(16).substr(2, 8)}`; // Unique client ID
// Initialize the AWS IoT MQTT Connection
connection = new iot.AwsIotMqttConnection({
endpoint: IOT_CORE_ENDPOINT,
protocol: iot.AwsIotMqttConnectionConfig.ConnectThroughWebSocket,
credentialsProvider: {
get: {
credentials: () => ({
aws_access_key_id: credentials.accessKeyId,
aws_secret_access_key: credentials.secretAccessKey,
aws_session_token: credentials.sessionToken,
}),
}
},
cleanSession: true,
clientId: clientID,
keepAlive: 30
});
// --- Event Listeners ---
connection.on('connect', () => {
console.log('Connected to AWS IoT Core!');
connectionStatusElement.textContent = 'Connected';
connectionStatusElement.style.color = 'green';
// Subscribe to the topic
connection.subscribe(MQTT_TOPIC, iot.QoS.AtLeastOnce)
.then(() => {
console.log(`Subscribed to topic: ${MQTT_TOPIC}`);
})
.catch(error => {
console.error('Subscription error:', error);
connectionStatusElement.textContent = `Connected (Subscription Failed)`;
connectionStatusElement.style.color = 'orange';
});
});
connection.on('message', (topic, payload) => {
console.log(`Message received on topic ${topic}: ${payload.toString()}`);
try {
const data = JSON.parse(payload.toString());
iotDataElement.textContent = JSON.stringify(data, null, 2);
} catch (e) {
iotDataElement.textContent = `Raw: ${payload.toString()}`;
console.warn('Received non-JSON message:', payload.toString());
}
});
connection.on('error', (error) => {
console.error('MQTT Connection Error:', error);
connectionStatusElement.textContent = `Error: ${error.message}`;
connectionStatusElement.style.color = 'red';
reconnectButton.style.display = 'block';
});
connection.on('close', () => {
console.log('MQTT Connection Closed');
connectionStatusElement.textContent = 'Disconnected';
connectionStatusElement.style.color = 'gray';
reconnectButton.style.display = 'block';
});
// --- Connect to IoT Core ---
await connection.connect();
} catch (error) {
console.error('Failed to connect to AWS IoT Core:', error);
connectionStatusElement.textContent = `Failed to Connect: ${error.message || error}`;
connectionStatusElement.style.color = 'red';
reconnectButton.style.display = 'block';
}
}
// --- Reconnect Button Handler ---
reconnectButton.addEventListener('click', () => {
if (connection && connection.isConnected) {
console.log('Already connected, no need to reconnect.');
return;
}
connectAndSubscribe();
});
// --- Initial Connection on Page Load ---
document.addEventListener('DOMContentLoaded', connectAndSubscribe);
const MQTT_TOPIC