S3 Pre-Signed URLs

In the course “Security Engineering on AWS” there is a section on S3. On one of the slides there is a bullet point:

Use pre-signed URLs for applications that refer to S3 objects

The course notes say:

“Make use of pre-signed URLs for applications that refer to S3 objects with anonymous access, e.g. downloading of restricted content. Authentication and authorization must be done in the application.”

One use case is as follows. You have an application which requires the customer to register with the application in order to access content, for example some videos in S3. You do not want to make the videos public as then anyone who knows the URL would be able to access them without paying.

The application would typically use the SDK to request a pre-signed URL. This is a URL with a temporary security token appended to it. The token expires in a configurable time. The token is validated by S3 when the object access is requested.

To test it:

Create a role and attach the policy S3FullAccess.

Launch an AMZ Linux EC2 Instance with the role attached.

SSH in to the instance, use aws configure as usual to choose  the a default region. You may need to research this bit if you don’t already have such an instance)

Issue the following commands (you will have to replace the bucket name, and you can use any file. I copied a jpg to the instance for this test)

aws s3 mb s3://bucket-presigned-urls
aws s3 cp file.jpg s3://bucket-presigned-urls

Now switch to the console, navigate to the object and click on the Object URL which will look something like this:

Object URL


You will get Access Denied. This is because the object does not have public permissions.

Back in the SSH terminal window, create a pre-signed URL:

aws s3 presign s3://bucket-presigned-urls/file.jpg --expires-in 60 

The –expires-in is optional. The default is 1 hour.

The output of the command will be similar to:

https://bucket-presigned-urls.s3.amazonaws.com/file.jpg?AWSAccessKeyId=ASIA26NEMI3H7GPEO2D5&Expires=1562947328&x-amz-security-token=XXXX <several lines of text ommitted>

Copy and paste the URL into a browser. It should work.

Wait 1 minute and try again. You should get “Access Denied. Request has expired”