Nick
Nick

Reputation: 3

AWS IoT: ForbiddenException: Forbidden when trying iotData.getThingShadow() in browser

I am working on browser script uploaded to EC2 to getThingShadow() using Federated Cognito credentials (Facebook login) but only get ForbiddenException: Forbidden

the login part was successful, i received credentials (non-empty) from AWS.WebIdentityCredentials()

The cognito ID was manually authorized using CLI (aws iot attach-principal-policy) Cognito_Auth_Rule was allowing iot:* too

looks like i did everything as per manual, still cannot get iotData

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/IotData.html

Please advise, really appreciate any comments

Thanks

Nick

My IAM Policy attached to Cognito_Auth_Rule is:

            {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": [
                            "iot:*"
                        ],
                        "Resource": [
                            "*"
                        ]
                    }
                ]
            }

get credentials

iotData.config.credentials = new AWS.WebIdentityCredentials({
    ProviderId: 'graph.facebook.com',
    RoleArn: roleArn,
    WebIdentityToken: response.authResponse.accessToken
});

my code

        var params = {
            thingName: 'thingName' /* required */
        };
        iotdata.getThingShadow(params, function (err, data) {
            if (err) {
                console.log(err, err.stack); // an error occurred
                iotResults.innerHTML = err;
            } else {
                console.log(data);           // successful response
                iotResults.innerHTML = data;
            }
        });

error message from console:

Error: Forbidden
    at Object.s [as extractError] (aws-sdk-2.7.20.min.js:37)
    at constructor.i (aws-sdk-2.7.20.min.js:37)
    at constructor.callListeners (aws-sdk-2.7.20.min.js:38)
    at constructor.emit (aws-sdk-2.7.20.min.js:38)
    at constructor.emitEvent (aws-sdk-2.7.20.min.js:37)
    at constructor.e (aws-sdk-2.7.20.min.js:37)
    at a.runTo (aws-sdk-2.7.20.min.js:39)
    at aws-sdk-2.7.20.min.js:39
    at constructor.<anonymous> (aws-sdk-2.7.20.min.js:37)
    at constructor.<anonymous> (aws-sdk-2.7.20.min.js:37) "ForbiddenException: Forbidden
    at Object.s [as extractError] (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:37:9704)
    at constructor.i (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:37:14284)
    at constructor.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:38:4687)
    at constructor.emit (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:38:4396)
    at constructor.emitEvent (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:37:23801)
    at constructor.e (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:37:19651)
    at a.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:39:11367)
    at https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:39:11574
    at constructor.<anonymous> (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:37:19861)
    at constructor.<anonymous> (https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js:37:23856)"

Upvotes: 0

Views: 2930

Answers (2)

David
David

Reputation: 1174

To read out the Thing Shadow via Browser using the iotdata.getThingShadow(); method like OP is using, you need to attach a Principal Policy.

In case anyone is wondering, how to automatically setup the iot.attachPrincipalPolicy that UXDart has mentioned:

 cognitoIdentity.getId(params, function(err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else{
          cognitoId = data.IdentityId;

          console.log('Cognito ID: ' + cognitoId);

          var iot = new AWS.Iot();

          iot.listPrincipalPolicies({principal: cognitoId}, function(err, data) {
            if (err) console.log(err, err.stack); // an error occurred
            else{
              console.log(data);
              var found = false;
              for(var i = 0; i < data.policies.length; i++) {
                if (data.policies[i].policyName == 'your-iot-policy'){
                  found = true;
                  break;
                }
              }
              if(found == false){
                console.log("Versuche Policy einzutragen...")
                iot.attachPrincipalPolicy({policyName: 'your-iot-policy', principal: cognitoId}, function(err, data) {
                  if (err) console.log(err, err.stack); // an error occurred
                  else     console.log("Policy eingetragen!");           // successful response
                });
              }else console.log("Policy gefunden!");
            }
          });
        }
      });

Upvotes: 0

UXDart
UXDart

Reputation: 2620

the IAM policy is fine... but you need to specifically set the IoT policy to that user... so when the user is created, or now when the user logs in... call

let iot = new AWS.Iot(); iot.attachPrincipalPolicy(

you should notice that method received the policyName, that is the name of the policy "in IoT policies" (not in IAM policies, so copy your policy in IoT) and the principal, that is the cognito user id

is not enough to give the IAM policy, you need to specify the attachPrincipalPolicy too

Upvotes: 1

Related Questions