sethro
sethro

Reputation: 2127

Restrict S3 Object Access to Specific Cognito Users

I am working on an application that will manage access to purchased files that are stored in S3. I have files organized by product in S3, for example:

my-bucket
  ├── product-a
  │     ├── file-1
  │     ├── file-2
  │     └── file-3
  ├── product-b
  │     ├── file-1
  │     ├── file-2
  │     └── file-3
  └── etc...

I am also using Cognito to manage user identities and authentication. I would like to create an IAM role that all users will assume which will grant them access only to the files of products they have purchased. What would be the proper way to do this? I have read thru Cognito's documentation and I feel I am just not quite connecting the dots.

I see from this example, that I could provide each user access to their own folder in a bucket, but then I would have to copy the files to each user's folder, which seems both inefficient and prone to error.

{
  "Version": "2012-10-17",
   "Statement": [
   {
     "Effect": "Allow",
     "Action": ["s3:ListBucket"],
     "Resource": ["arn:aws:s3:::my-bucket"],
      "Condition": {"StringLike": {"s3:prefix": ["cognito/myapp/"]}}
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket/myapp/${cognito-identity.amazonaws.com:sub}",
        "arn:aws:s3:::my-bucket/myapp/${cognito-identity.amazonaws.com:sub}/*"
      ]
    }
  ]
}

But I was hoping to create a policy that would grant a user access to the folder of product-a if and only if they had purchased that product, say using some flag that was contained in that user's Cognito Sync data.

Is this possible? Am I just not using the correct tools? I think this must be a common use-case.

Upvotes: 13

Views: 2289

Answers (2)

Farhad
Farhad

Reputation: 97

A possible solution could be Aws Presigned URLs Read more here. The idea is you request a temporary url in order to give an access to the specific s3 objects with an expiration time.

Upvotes: 0

Daniel Blignaut
Daniel Blignaut

Reputation: 121

In my use case, this was possible because of the following:

  1. I upload a file to s3
  2. I have a lambda listening to S3 events that interprets this file created and creates an entry in DynamoDB (our app's database engine). However, this entry contains a url to access this file which is not the s3 url. Instead it's an API gateway url that proxies the request and has a custom lambda authorizer on it. This lambda authorizer then validates user access by looking at the cognito token and lets me add completely fine-grained access for other users whilst still letting the core user / owner manage the file using the S3 sdk client directly and with the correct cognito Identity roles attached to the bucket permissions.
  3. the user then requests this image with the Authorization cognito token header in the request, this is processed by API gateway and the relevant response is returned.

Upvotes: 2

Related Questions