Secure Uploads to AWS S3 with Ruby on Rails

Paulo Carvalho
3 min readAug 13, 2020

Do not expose your secrets on the client. The following guide will outline how to upload files directly to S3 without exposing your secret tokens.

Photo by Philipp Katzenberger on Unsplash


A direct upload to the storage server (S3, GCP storage, etc) may be desired when working with large files. Since uploading through the server would consume resources with the handling of these long running requests.

A possible (yet vulnerable) approach to implementing direct uploads is pictured below. In it, a client uploads a file directly to S3 using credentials it already has (usually that allow any upload) and when the upload successfully completes the client makes a POST request to the server indicating a new file has been uploaded. However, this approach exposes the S3 secrets and would allow a bad agent to upload any file (and possibly overwrite existing files).

The addition of an extra step increases the security of the upload by not exposing secrets and allowing the server to validate the request (check authorization, etc). This new flow is shown below.

Example with Code


You will require the official aws-sdk-s3 gem to be installed and configured with your credentials and region.

Step 1: Method for Generating Signed URL

In your model (ex: models/attachment.rb) add a class method for generating a signed URL for S3 upload.

def self.generate_upload_url(file_name)
bucket: ENV['MY_S3_BUCKET_NAME'],
key: file_name,
use_accelerate_endpoint: true,
expires_in: 300 # Number of seconds the URL is valid for

Step 2: Add Controller for Generating a Signed URL

Paulo Carvalho

Want to chat about startups, consulting or engineering? Just send me an email on