Disconnect AWS IoT device after it's connected
Asked Answered
K

2

6

I'm working on a web application where the user can login with AWS Cognito. After login with the AWS credentials I'm connecting to AWS IoT device like

var device = AwsIot.device({ 
    clientId: clientID, 
    host: host, 
    accessKeyId: credentials.accessKeyId, 
    secretKey: credentials.secretAccessKey, 
    protocol: 'wss', 
    sessionToken: credentials.sessionToken, 
    offlineQueueing: 'false' 
}); 

Then once the user logout from the app using AWS Cognito using

cognitoUser.signOut(); 

Then after logout I want to disconnect the the AWS IoT device as well. Right now I'm seeing even after the logout the device is listening to the events like

device.on('close', function() {}) 
device.on('error', function() {}) 
device.on('offline', function() {}) 

Can someone please specify which function should I call to disconnect the device as well so that it don't listen to these events as well.

I was going through the doc https://github.com/aws/aws-iot-device-sdk-js But I didn't got any specific function for this.

Moreover I used the AWS credential to connect the AWS IoT device, and once I logout from Cognito then the device should have been automatically disconnected as well I think. Please let me know what should be the approach here.

Kickshaw answered 16/2, 2018 at 13:41 Comment(0)
K
5

I got the answer from AWS IOT support team on this.

The AwsIot.device class is a wrapper for the MQTT class with helpers to assist with connecting to AWS endpoints To disconnect your device, you can call device.end(); This will close your connection and invoke device.on('close'). As for Cognito Sign-out. This will not invalidate the session credentials already provided by Cognito which were used to establish the connection. They will continue to be valid until their assume role time expires.

Kickshaw answered 18/2, 2018 at 18:41 Comment(1)
Hi, i came here facing the same issue with Amplify PubSub...the previous user's connection-subscription was still valid on current user's session (except if i manually reload page or by calling` PubSub.removePluggable()` ) Handling connection termination on the front-end is far from a good practice, did you found a better solution?Trihedron
M
0

You can force clients to disconnect by using the property of AWS IoT core that at any time only one given client identified by clientId may be connected to the broker.

Thus, when you need to forcefully disconnect a certain client, you can initiate a connection with a new client - with different credentials - and the same clientId.

This code does that from within a Lambda function that has the necessary IAM policies attached; it uses the AWS session by passing the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN to the AWSClientIoT.device() function:

import * as AWSClientIoT from 'aws-iot-device-sdk';
import { DescribeEndpointCommand, IoTClient } from '@aws-sdk/client-iot';

// Find out address of endpoint
const endpoint = await new IoTClient({}).send(new DescribeEndpointCommand({ endpointType: 'iot:Data-ATS' }));
const host = endpoint.endpointAddress;

this.logger.info(`Initiating disconnect of device ${deviceUuid.toString()} @ ${host}`);
const client = new AWSClientIoT.device({
  protocol: 'wss',
  accessKeyId: mustGetEnv('AWS_ACCESS_KEY_ID'),
  secretKey: mustGetEnv('AWS_SECRET_ACCESS_KEY'),
  sessionToken: mustGetEnv('AWS_SESSION_TOKEN'),

  // Using the deviceUuid as the clientId is done by the device. Using this violates
  // the requirement that clientIds have to be unique on the device gateway, so the
  // original device will be disconnected.
  clientId: deviceUuid.toString(),
  host,
  connectTimeout: 1000,
  resubscribe: false,
});

// Wait until connected, when this resolves the "remote" client
// has been forcefully disconnected
await new Promise<void>((resolve, reject) => {
  client
    .on('connect', () => {
      this.logger.debug('Connected!');
      resolve();
      return;
    })
    .on('reconnect', () => this.logger.debug('Reconnecting'))
    .on('offline', () => this.logger.debug('Offline'))
    .on('error', (error) => {
      this.logger.error(error);
      reject(error);
      return;
    });
});

// Disconnect ourselves
await new Promise<void>((resolve) =>
  client.end(true, () => {
    resolve();
  }),
);
Motch answered 16/11, 2022 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.