I know this is an old question, but I wanted to post my experiences getting the vague AMQJS0008I Socket closed (error nr 8) message from Amplify.
Related git issue: #2739
From my concern it always kicks you out because of a permission problem and the answers are a little bit spread around everywhere.
From my point of view putting a "*" message in a policy is not the most secure thing to do. That's why I post my findings here:
First step
Make sure your IAM AuthRole from Amplify has the right permissions. The Authrole name is something like amplify-yourappname-dev-...-authRole (You can always find it in cloudformation console) and it must have following policies attached:
- AWSIoTConfigAccess
- AWSIoTDataAccess
From this point on your Amplify app can start accessing AWS IoT
Second step
This step needs to configure AWS IoT Console to allow certain Cognito User Id's to publish/subscribe to specific topics.
Create a policy with following contents:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:eu-central-1:************:client/${iot:ClientId}"
},
{
"Effect": "Allow",
"Action": [
"iot:Publish",
"iot:Receive"
],
"Resource": [
"arn:aws:iot:eu-central-1:*************:topic/whatevertopic/*",
"arn:aws:iot:eu-central-1:*************:topic/$aws/things/whateverthingname/shadow/*"
]
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": [
"arn:aws:iot:eu-central-1:************:topicfilter/whatevertopic/*",
"arn:aws:iot:eu-central-1:************:topicfilter/$aws/things/whateverthingname/shadow/*"
]
}
]
}
Take not that:
Publish
and Receive
need the topic subject prefix
Subscribe
needs the topicfilter prefix
This took me a long time to find out but it is correct.
Third step
You must allow specific cognito IDs to specific policy. You can connect a policy to a Cognito ID target. I created a Python Lambda function to do so, but can be done through the CLI for testing
aws iot attach-policy --policy-name 'myIoTPolicy' --target '<YOUR_COGNITO_IDENTITY_ID>'
The COGNITO_IDENTITY_ID is the output of my Vue Apps Amplify Auth module. See next step
Step Four
The last step is the app itself. This is the code which made it work for me:
import Amplify, { Auth, PubSub } from 'aws-amplify'
import { AWSIoTProvider } from '@aws-amplify/pubsub'
const region = 'eu-central-1'
const loginUserCredentials = await Auth.currentCredentials()
// This log shows the user ID somewhere in the object.
// It must be in following style: region:ID
console.log(loginUserCredentials)
Auth.essentialCredentials(loginUserCredentials),
region: region
})
const awsiotprodvider = new AWSIoTProvider({
aws_pubsub_region: region,
aws_pubsub_endpoint: 'wss://*****************-ats.iot.eu-central-1.amazonaws.com/mqtt'
})
Amplify.addPluggable(awsiotprodvider)
// Can be interesting for testing:
Amplify.Logger.LOG_LEVEL = 'DEBUG'
PubSub.subscribe('$aws/things/whateverthingname/shadow/get/accepted').subscribe({
next: (data: any) => console.log('Message received', data),
error: (error:any) => console.error(error),
complete: () => console.log('Done')
})
setTimeout(async () => {
await PubSub.publish('$aws/things/whateverthingname/shadow/get', { msg: '' })
}, 5000)
This code works perfectly for me!
Good luck!
Hacor
Interesting reads: