Uploading files into s3 bucket

Posted on Friday · August 25 2017 · 12:00 AM | 321 words · 2 min read

This week I had to implement a feature where users would be able to upload files directly to our s3 bucket from their browser.

Among different techniques we decided to upload using POST method with AWS Signature version 4.

The workflow kinda goes like this:

  • user goes to our webpage
  • select files to upload
  • gets a policy and signature for those selected files
  • upload directly to s3

We delegated the generation of policy and signature to a serverless function.

Setting Origin

We had setup the policy such a way that after the file upload it’ll redirect to a specific page. We were getting a 403 status since cors was enabled and the Origin was set to null!

So, I looked for how to set the Origin to localhost or something like that. After some digging, I find out you can’t just set the Origin programmatically since it compromises the security.

Turns out we were using webpack-dev-server for development and we hadn’t set any host name there.

Time drifting

We fixed that Origin issue and next we were getting policy expired error from s3.

s3 requires that the time of the server which is generating the policy syncs with the AWS server.

I was using docker for development environment, and after a little googling I found that the time inside the container might not match the host sometimes. Especially time drifts happen when the host is kept to sleep.

So, I updated the time with ntpdate from http://pool.ntp.org and turns out it was already in sync with the host machine!

Type inference in JS

So I looked into the policy generating function in our AWS Lambda console. And there was that culprit. I had to set the expiration time, and while doing it I was ‘adding’ integer with a date string! And javascript being a cute language instead of adding as numbers it concatenated as a string.

new Date(Date.now()).toISOString()+EXPIRATION_TIME -> new Date(Date.now()+EXPIRATION_TIME).toISOString()