0

I want my Cognito authenticated users (through google identity provider) to access bucket objects publically without needing any x-Amz-Security or Signature token.

In my app, authenticated users upload 100 images daily, and I can't store each image URL with a token in Dynamodb, because it is only valid for 7 days, after 7 days its token changes. Another way to access the bucket objects is requesting a getObject call, which requires a key (filename) and returns object/image URL with a token (and expiry), which I can use to render an image, but I don't want to make an extra call to get the tokenized URL. So I want my authenticated users to get public access to all objects in my bucket.

For this I am using Amplify, and storage can be added in the app using amplify add storage. I tried writing bucket policy, but it is not working for me:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": {
                "Federated": "accounts.google.com"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::<bucketname>-staging"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "accounts.google.com"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::<bucketname>-staging/*"
        }
    ]
}

The above policy didn't work, I still need a token to access the image/object from the s3 bucket. I also tried this principle, but it allows public access to objects, which means an unauthenticated user can also get access to it.

{
                "AWS": "*"
            },

After this, I created an Identity pool, with help of my Cognito pool ID and google id. And grant it read, write and list permission. But still authenticated users still need a signed URL, I want to allow them to access it with a single go, with an unsigned URL.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
HackRx
  • 198
  • 2
  • 14
  • [link](https://github.com/aws-amplify/amplify-cli/issues/7994) to the question which I asked on amplify-cli repository. – HackRx Aug 20 '21 at 21:56
  • I have followed this article to create [Identity Pool](https://medium.com/@sumindaniro/user-authentication-and-authorization-with-aws-cognito-d204492dd1d0) – HackRx Aug 23 '21 at 20:03
  • I'm not sure if I understand the problem. So you have an authenticated user. With the help of Identity Pool you exchanged the ID token for a set of temporary credentials. With those credentials your authenticated user can make a `getObject` call to whatever resources you specified in the policy. Where is exactly the problem? And what it has to do with direct links to S3? – Aleksander Wons Aug 24 '21 at 06:56
  • @AleksanderWons Actually, I am not calling getObject call at the front-end, and I don't want to. I just want to allow my authenticated users to access the bucket images with the "/public/key" URL only. No token or signature should be needed. To be more clear, my "Restrict All Public Access" is off at the bucket and global level. – HackRx Aug 24 '21 at 13:24

1 Answers1

1

If I understand your question correctly, to access non-public S3 objects you don't want to:

  • sign the request to S3
  • use the provided API and temporary credentials

The problem here is that to access restricted objects in S3 you have to use one of the two possible mechanisms:

  • sign the request to S3
  • use the provided API and temporary credentials

Somehow you need to tell S3 who is requesting the file. In your case, it is the federated user. You can tell it by signing the request with the security token obtained from STS or by using SDK to exchange the ID token for a set of temporary credentials and then making a signed call to S3 API.

If I understand you correctly - you don't want to do either of those things. In that case, you are out of luck. You won't be able to implement what you wish to the way you intended to.

Aleksander Wons
  • 3,611
  • 18
  • 29
  • 1
    Thanks @aleksanderwons, I figured it out late, and you were right. We either need a presigned URL or we need to call the getURL function in order to fetch the image from the bucket. And talking about my concern for getURL call, it is not a network call, it is just a local call, which concats credentials to passed key. So now I am using the getURL func. to get tokenized URL. reference to this : (IOS code link)[https://github.com/aws-amplify/aws-sdk-ios/blob/main/AWSS3/AWSS3PreSignedURL.m#L307] – HackRx Sep 15 '21 at 22:03