2
votes

Getting this error while using AWS JS SDK + DynamoDB:

AccessDeniedException: User: arn:aws:its::[accnt id]:assumed-role/dynamoIntroRole/web-identity is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-west-2:[accnt id]:table/websiteTest

This is the HTML / JS I had used:

<title>Insert title here</title>
</head>
<body>
<button id="login">Login</button>
<div id="fb-root"></div>

<script type="text/javascript">
var fbUserId;
var dynamodb = null; 
var appId = '120636118298132'; //from facebook
var roleArn = 'arn:aws:iam::[my account id deleted]:role/dynamoIntroRole'; //from AWS IAM

window.fbAsyncInit = function() {
	FB.init({appId : appId});
	
	document.getElementById('login').onclick = function(){
		
	FB.login(function (response)  
	{
		if(response.authResponse)
		{
			AWS.config.credentials = new AWS.WebIdentityCredentials({ //WIF
				RoleArn: roleArn,
				ProviderId: 'graph.facebook.com',
				WebIdentityToken: response.authResponse.accessToken
			});
			
			var dynamodb = new AWS.DynamoDB({ region: 'us-west-2' });
			var docClient = new AWS.DynamoDB.DocumentClient({ service: dynamodb });
			console.log("You're now logged in.");
			var params = {
					TableName: 'websiteTest',
				    Item: {
				        itemID:'lkjljljlkjlkjlkjlkjlkj',
				        f2:'kjhkjhkjhkjhkjhkjhkjhkjhkjh'
				    } 
				};
				docClient.put(params, function(err, data){
				    if (err) console.log(err);
				    else console.log(data);
				});
		}
		else
			{
			console.log("Issue logging in");
			}
		
	}); //end fb login
	
		};
	};
	// Load the FB JS SDK asynchronously
	(function(d, s, id){
	   var js, fjs = d.getElementsByTagName(s)[0];
	   if (d.getElementById(id)) {return;}
	   js = d.createElement(s); js.id = id;
	   js.src = "//connect.facebook.net/en_US/all.js";
	   fjs.parentNode.insertBefore(js, fjs);
	 }(document, 'script', 'facebook-jssdk'));
</script>

</body>

Here is the IAM policy I attached to the role used:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:UpdateItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:us-west-2:[my account deleted]:table/websiteTest"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${graph.facebook.com:id}"
                    ]
                }
            }
        }
    ]
}

What am I missing?

2

2 Answers

5
votes

The issue you are experiencing has to do with the condition specified in the IAM policy. It currently specifies a fine-grained access control.

"Condition": {
            "ForAllValues:StringEquals": {
                "dynamodb:LeadingKeys": [
                    "${graph.facebook.com:id}"
                ]
            }
        }

The condition requires that the partition key match the Facebook id used. If you do not have the specified partition key, then it will throw an AccessDeniedException.

So you will either need to create a table with the Facebook id as the partition key or remove the condition from the IAM policy. Also note that the partition key needs to be a string in order to use fine-grained access control.

Resources:

Fine-Grained Access Control for DynamoDB

Example Policies for Fine-Grained Access Control

2
votes

I've tested your HTML code and it is working. The way your IAM policy is set up could be reason for AccessDeniedException. I would suggest following the format prescribed in AWS SDK for JavaScript in the Browser > Create an IAM Role to Assign Users Logged in through Facebook (http://aws.amazon.com/developers/getting-started/browser/). This worked for me. I hope it helps.

My IAM policy is:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::bookdashjs/facebook-${graph.facebook.com:id}/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::bookdashjs"
            ],
            "Effect": "Allow",
            "Condition": {
                "StringEquals": {
                    "s3:prefix": "facebook-${graph.facebook.com:id}"
                }
            }
        }
    ]
}