Home > Blockchain >  how to allow s3 images/object to be downloaded only from by website request using presigned url?
how to allow s3 images/object to be downloaded only from by website request using presigned url?

Time:12-03

I am in serious trouble. I have been uploading to the s3 bucket using aws-sdk javascript, downloading it through object link. Using s3 to store images/assets to be used for the nextjs website. I have set the bucket to the read only for everyone. I just realize that this is serious problem, as anyone will be able to download from my bucket unilimited time, and the cost will be through the roof. How can I secure the download to be only from my website through presigned link(I haven't configured the presigned link on my side)? Please help me. I will provide more details below:

current bucket policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::bucketname/*"
        }
    ]
}

CORS:

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "DELETE",
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "x-amz-server-side-encryption",
            "x-amz-request-id",
            "x-amz-id-2"
        ],
        "MaxAgeSeconds": 3000
    }
]

CodePudding user response:

To restrict access to your Amazon S3 objects so that they can only be downloaded from your website using presigned URLs, you will need to update your bucket policy and CORS configuration to allow requests only from your website's domain.

First, update your bucket policy to restrict access to the s3:GetObject and s3:GetObjectVersion actions to only requests that come from your website's domain. You can do this by replacing the Principal element in your bucket policy with the following:

"Principal": {
    "AWS": [
        "arn:aws:iam::<YOUR ACCOUNT ID>:root",
        "arn:aws:iam::<YOUR ACCOUNT ID>:user/<YOUR USER NAME>"
    ],
    "Web": [
        "http://<YOUR WEBSITE DOMAIN>/*"
    ]
},

Next, update your CORS configuration to allow requests only from your website's domain. You can do this by replacing the AllowedOrigins element in your CORS configuration with the following:

"AllowedOrigins": [
    "http://<YOUR WEBSITE DOMAIN>"
],

CodePudding user response:

You can restrict access to objects based on the 'referring' website.

From Bucket policy examples - Amazon Simple Storage Service:

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Effect":"Allow",
      "Principal":"*",
      "Action": "s3:GetObject",
      "Resource":"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Condition":{
        "StringLike":{"aws:Referer":["http://www.example.com/*","http://example.com/*"]}
      }
    }
  ]
}

However, restricting access with referer is not secure since it is easy to fake this information.

The more secure method would be to use Amazon S3 pre-signed URLs, which provide time-limited access to private objects in Amazon S3. These URLs must be generated by your back-end, typically after a user has authenticated to your website. This is ideal for serving private/confidential content.

However, if you are simply serving content for a normal website that does not require authentication, then referer is more appropriate.

  • Related