Access denied when uploading S3 Objects - javascript

I'm following this tutorial of adding/listing objects from S3.
At first, I had problem to list objects because of Access Denied error, so I found that I have to to add additional permission s3:ListBucket and resource arn:aws:s3:::my-bucket to the role created by cognito to unauth user:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
Now, when I try to upload a file, I'm getting another Access Denied.
Am I doing something wrong or this tutorial has so many errors?
Additional Checks:
bucket has CORS
I didn't change any permissions of bucket after creating it (everything default)
I'm using proper Cognito Identity Pool ID ( I can list albmus )
I can delete album
After Access Denied error I can see that there is new identity in cognito unauth, so script works properly.
Owner of the bucket (me) has read/write access to the bucket

I'm not sure how cognito works internally and it might be playing with the ACL of the s3 object. So, adding s3:PutObjectAcl and s3:GetObjectAcl operations access might help. Additionally, if your code is doing multipart uploads to S3, you should consider adding s3:ListBucketMultipartUploads operation access. s3:PutObject operation already adds the permissions for Initiate Multipart Upload, Upload Part, Complete Multipart Upload.

Add IAM role with the policy, this will enable the user to upload any file with API or by the console.
{
"Version": "2012-10-17",
"Id": "1",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::777777:user/myuser"
]
},
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:DeleteObject",
"s3:GetObjectAcl"
],
"Resource": [
"arn:aws:s3:::bucketname/*",
"arn:aws:s3::: bucketname"
]
}
}

Related

How do I find out what is actually set to "${ ... }" in AWS IAM policy?

I'm trying to limit access to items in Dynamo DB tables based on Cognito User Pool using Lambda IAM role policy.
In the process, I'm struggling to find what is actually set to "${cognito-identity.amazonaws.com:aud}" in the Lambda IAM policy below.
{
"Effect": "Allow",
"Action": [
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:DescribeTable"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:aud}"
}
},
"Resource": "arn:aws:dynamodb:ap-southeast-2:*:*"
}
I'm assuming it is either Application Client ID or Identity Pool ID like "ap-southeast-2:xxxxxxxx-aaaa-bbbb-cccc-123456789012", but is there a way to output what is actually set to "${cognito-identity.amazonaws.com:aud}" on runtime to confirm?
I am relatively new to AWS.
Updated - Additional Information
Just before calling the Lambda via API Gateway, I can see something like "xxxxxxxxnv0ff03e9joqh3om3h" (my App Client ID) using below:
const session = await Auth.currentSession();
alert(session.idToken.payload.aud); //something like "xxxxxxxxnv0ff03e9joqh3om3h"
However, I get AccessDeniedException in Lambda DynamoDB query with the App Client ID.
ExpressionAttributeValues: {
":partitionkey": "xxxxxxxxnv0ff03e9joqh3om3h",
},
I can avoid AccessDeniedException error by changing the IAM Policy to:
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "123abc"
}
},
and my Lambda DynamoDB query to:
ExpressionAttributeValues: {
":partitionkey": "123abc",
},
I've tried Cognito Identity Pool ID too, but no luck.
The mapped values for aud and sub are provider specific and outlined in the documentation.
In the case of Cognito Userpool federation it will be set to the client ID.

How to access oauthIdToken returned from Firebase?

I'm trying to get the oauthIdToken of the result fetched from signing with firebase using signInWithCredential. I get the following back upon a successful login:
user Object {
"additionalUserInfo": bg {
"isNewUser": false,
"profile": Object {
"at_hash": "aWhmsdfeef32388EYD8YA",
"aud": "100423452193-gvmasfasdfasdfasfda7ee0.apps.googleusercontent.com",
"azp": "100406623293-gvmt0erkkob6asdfadfi7ee0.apps.googleusercontent.com",
"email": "fake#gmail.com",
"email_verified": true,
"exp": 1579142529,
"family_name": "last name",
"given_name": "first name",
"iat": 1579138929,
"iss": "https://accounts.google.com",
"locale": "en",
"name": "first last name",
"nonce": "Ow_sVcasdf50LdbHdTaro",
"picture": "https://lsfasfa.googleusercontent.com/-iKnasfasdf34/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3re9asdfas7_Erg/s96-c/photo.jpg",
"sub": "100824234342680931658",
},
"providerId": "google.com",
},
"credential": Object {
"oauthAccessToken": "ya29.Il-5B47AOKYEQ5NYikv93gYyyhWu_2FEHEaadfaasfasdfasdfBVJCDXG3HJ9MdqalyyxvZ-6jMoqRsaGzhPUg6Cg862vF25xocHR6rnbh_-HuP2MMey4s59Gx8fXLwgQ99dQ",
"oauthIdToken": "eyJhbGciOiJSUzsdfagyZDgyMDQwM2VlODUxOGM0YWFiYjJiOWZlMzEwY2FjMTIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291joiZW4iLCJpYXQiOjE1NzkxMzg5MjksImV4cCI6MTU3OTE0MjUyOX0.i-YiWbokasfiP_-xWCHJUyT_aLWp7eb3YCE6mzRUbbuKsdfsdfHptczrMXB5vMZY_5JFp8ZD2zxoNlvhTpuMY3B_zw_5Irk6HzuHGHXyAgzNJjh5n6cYR8gOiOsfsdfcKATpHcG7H_gOCwns_fI44I820qcmrogaEXuW-i3u9X5aXbTYqW5EaZQvQzuHkYHO2VWoktOTZsfsdfsfOaYYGU-tqW-ygAB_aWD7VPjIuUY4ySPF4k6IRR1x3ZysfdsdfdGGarX3isPGxMrDMtbRtsfsdfVaKsZdRtCpbfNUbFO8NR6x-pIvKsdfA",
"stsTokenManager": Object {
"accessToken": "eyJhbGciOiJSUzI1NiIsASDAFASFVmZTJlZDQyOWI3MzY0M2Y2NTEiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoicmVudGVyaWkgcmVudGVyaGUuY29tIn19.n7z7HlL9lU7VEOA4fGIHvE9UMLSu5uo1rpfTm6m-N5A8CaKQaDu96sAvsG8iOVx8PYnytadffsafSRHyJoS0bzZbpQS6-YItdM5bIPxLMTFYEb0-Ho-tPnhRBSfWfPqJnK0c18YBFtHTG-0TvLNppmuZFG9AJjZZr0ASIkoOWmkI0gdOUAKBkutwMb3oitxeorT-pUdtKB5Rk23ekewz05oi7R5TI4xpBX5LsPvqaCqI4S5wxHe_BilRiiMhxd_lINdWftEkpctKSApJubML7mB9A",
"apiKey": "AIzaSysdfsdfsiWO7_2buk",
"expirationTime": 1579142530341,
"refreshToken": "AEu4IL01n_G6c4_Wg6fzseXRGPJHEAJnhzw7GLZVTS4RICikJ8PUgmmtNWXjcttOSbmYVCJDzGluUvTNKPHa4aS8gG0R3ijmrvPpcyJFPWZ5dRRDIlzxuoSyt70mewdRYgK4Eao7W21550slj7qHu8ZT_1bACJb31e_y7UnL2QjJEuvKwcWII8v8mgMPpYC2RH6fKg0Xrv9XLBgTxso25KfDrlfHBfYp4t35CzcVqODl71663_xV0WHhQ5gpv1hW0N39MMU5S0UEbQ_FnMmcJUFygaRvHndj2yNVhGwv_Re0uut3hUanPO_bo6OT4VEgIEEZ6cuiq8jzpH_T7d6bwI9eLZNS6IC1Fu8EJFmUWAtsdyBErq0s39gj2uta0uqLIGP_wlP5F_eDiw",
},
"tenantId": null,
"uid": "KlGB4adfadfn9ktr1",
},
Trying to access oauthIdToken with console.log(result.credential.oauthIdToken) inevitably provides null even though the variable is clearly present. I'm assuming this is similar to getting the accessToken within stsTokenManager where you can only get it using the method getIdToken() and credential.stsTokenManager.accessToken provides null.
How do I access oauthIdToken?
It took me a day to sort this one out. I was looking at using promises and found the answer by logging the parts of the object.
The output of printing out the result object is very confusing. The issue is that the JSON object representation has keys which don't correspond to the variables on the object. If you use console.log(JSON.stringify(result.credential)) rather than
console.log(JSON.stringify(result)) you will see the different variable names.
To see the OAuth Identity Token use console.log(console.log(result.credential.idToken)) without the oauth prefix. Likewise the access token doesn't have the oauth prefix.
It is important to know that in the Google/Firebase world there are two different types of identity token. The Firebase identity token is obtained from user.getIdToken(). It is sent to the server to allow the client to be verified. Its audience in the project identifier. The other type, which is the subject of the question, is the identity token generated by the Auth provider. If the Auth Provider is Google then this is the token you have to use to authenticate against Cloud Functions and Cloud Run services. The token needs to be sent in a Authorization: Bearer idtoken header on the request.

Firehose is unable to assume role

I'm trying to use Firehose API (JS) and I keep getting the following error:
"InvalidArgumentException: Firehose is unable to assume role
arn:aws:iam::XXXXXXXXXX:role/NAME. Please check the role provided.
I check the role and I have set my custom policy to include all resources for STS and Firehose action. I have no clue why this error exists if I'm allowing AssumeRole under STS.
Method Calling
The method I'm using is createDeliveryStream(params = {}, callback) with S3DestinationConfiguration.
Policy JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:*",
"kinesisvideo:*",
"s3:PutAccountPublicAccessBlock",
"s3:GetAccountPublicAccessBlock",
"s3:ListAllMyBuckets",
"s3:*",
"firehose:*",
"sts:*",
"s3:HeadBucket"
],
"Resource": "*"
}
]
}
Please check the trust relationship defined in the IAM role and verify that it is set to firehose.amazonaws.com. Policy defined in Trust relationship enables services to assume the role. For Kinesis Firehose, refer this document which contains details about IAM roles for Firehose. Refer "Grant Kinesis Data Firehose Access to an Amazon S3 Destination" section in the document which mentions about trust policy.

Facebook open graph doesn't return any instagram media

I have opened this as a bug with facebook here https://developers.facebook.com/bugs/105273653568982/
but thought I would ask here as well to see if anyone else has a solution:
The facebook open graph API says it is supposed to work for instagram as well as facebook, however when used from my server side code OR from the open graph explorer OR from postman, is only returning facebook media items, not instagram media items.
Eg a GET request for comments on my own facebook photo returns successfully:
Request:
https://developers.facebook.com/tools/explorer?method=GET&path=101205943227587%2Fcomments&version=v2.11&access_token=MYACCESSTOKEN
Result:
{
"data": [
{
"created_time": "2016-01-04T16:11:07+0000",
"message": "People might be abl",
"id": "101205943227587_1187008471313990"
}
],
"paging": {
"cursors": {
"before":"WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEU0TnpBd09EUTNNVE14TXprNU1Eb3hORFV4T1RJek9EWTQZD","after":"WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEU0TnpBd09EUTNNVE14TXprNU1Eb3hORFV4T1RJek9EWTQZD"
}
}
}
whereas endeavouring to get the same thing for an instagram post (again using my own media) doesn't work.
Request:
https://developers.facebook.com/tools/explorer?method=GET&path=1531969816055084767%2Fcomments&version=v2.11&access_token=MYACCESSTOKEN
Result:
{
"error": {
"message": "(#803) Some of the aliases you requested do not exist:
1531969816055084767",
"type": "OAuthException",
"code": 803,
"fbtrace_id": "D2xUM/kQWsJ"
}
}
None of the methods here
https://developers.facebook.com/docs/instagram-api/overview/
work for instagram media, eg attempting to get the info about Instagram's own account
GET graph.facebook.com
/25025320?fields=biography,id,username,website&access_token=MYACCESSTOKEN
returns an error
{
"error": {
"message": "Unsupported get request. Object with ID '25025320' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api",
"type": "GraphMethodException",
"code": 100,
"error_subcode": 33,
"fbtrace_id": "DCreoeyTARt"
}
}
My app has been approved to use the new api with the instagram_basic and instagram_manage_comments permissions, and I know the access token is valid as I am able to get facebook media and use the graph.facebook.com/me api so not sure why all instagram-related stuff is failing.

How to set the access control for microservices

I use Loopback Framework to create several services and I use an api gateway (tyk) to manage them.
Unfortunately I do not see how to set the access control for each of them.
I do not want a user to access data that does not belong to him.
Many thanks,
you can easily use two methods to secure your model.
1.From model.json file
inside your model model.json you can include ACL objects.
"acls": [{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}, {
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}]
2.Using operational hooks in model.js file
you can use operational hooks to manipulate security.
example
Template.observe('access', function (ctx, next) {
if(ctx.options.team){
var teamId = ctx.options.team.teamId;
ctx.query.where= ctx.query.where || {or :[ {user_created : 0},{teamId : teamId}]} ;
next();
}
});
hope this will be helpful.

Categories

Resources