It's very important to understand the difference between IAM
policy and AWS IOT
policy here. Suppose you use cognito user pool
as your identity provider.
First you need to set up a cognito identity pool
, link the identity pool to your user pool
and assign a role(attach IAM
policy to this role) to this identity pool.
Second, in your app, you first login so that you get the user pool credential, then you call
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-west-2:b8d2b32b-cbab-4ae3-9d47-1624d09c9350',
Logins: {
'cognito-idp.us-west-2.amazonaws.com/${userPoolIdentity}': userPoolCredential.getIdToken().getJwtToken(),
}
});
to exchange your user pool credential with aws temporary access credential:
AWS.config.getCredentials(e => {
if(e) console.log("Get credential failed", e);
this.device = AwsIot.device({//AwsIot is the aws-iot-sdk package
clientId: clientID,//clientId is just random string
host: '*-ats.iot.us-west-2.amazonaws.com',//replace * with your own host
protocol: 'wss',
accessKeyId: AWS.config.credentials.accessKeyId,
secretKey: AWS.config.credentials.secretAccessKey,
sessionToken: AWS.config.credentials.sessionToken
});
this.device.on('connect', function() {
console.log("DEVICE CONNECTED");
});
this.device.subscribe('test');
this.device
.on('message', function(topic, payload) {
console.log(`TOPIC IS ${topic}\nMESSAGE IS ${payload.toString()}`);
});
});
But the above code will not work!!!
Here is the tricky part: the credentials you get by exchanging your user pool credential is just a temporary credential that represent the AWS IAM
policy you just attached to your identity pool! When it requested to connect with your IOT, AWS will check if it's allowed to request and if it's allowed to do what the user requested. You already got the IAM
policy so you are allowed to request, but it will check the AWS IOT
policy attached to this identity. Since you haven't done this, you are not allowed to do what you really requested(namely connection). So at the first time you want to connect, you should attach a IOT
policy to this identity. You can do this either by command line or
(<AWS.CognitoIdentityCredentials>AWS.config.credentials).refresh(e => {
if(e) console.log('error', e);
const principal = (<AWS.CognitoIdentityCredentials>AWS.config.credentials).identityId;
console.log(`IdentityId: ${principal}`);
this.attachPrincipalPolicy("test-delete-after-use", principal);
});
attachPrincipalPolicy(policyName, principal) {
new AWS.Iot().attachPrincipalPolicy({
policyName: policyName, // you need to create policy beforehand in iot
principal: principal
}, err => {
err ? console.log('ATTACH PRINCIPAL POLICY ERROR', err) : console.log('ATTACH PRINCIPAL POLICY SUCCESS');
});
}
Now, when the identity tries to connect with IOT, IOT will find a IOT
policy attached to this identity, and approve this connection.
Sorry about the bad wording. In summary, you need to clarify the difference between IAM
policy and IOT
policy. This is just what I understand, it may have incorrect places. If you find it, please leave a comment or edit my answer.
IMPORTANT
Just found the relation between these two policies from official doc:
https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html
Look at section Policies for HTTP and WebSocket Clients