Generating Amazon S3 file upload Policy in Node.js

I recently (by recently, I mean two days ago) had to upload files — images to be precise — to a newly created Amazon S3 bucket. After going through a few documents online and following instructions (at least, I think I did), I had my environment (MEAN — MongoDb, Express, AngularJS and Node.js) setup for the upload.

On trying the upload, Amazon returned an error telling me the policy I was using was not the same as that which they generated. Apparently, I did something wrong somewhere so I sought to right my wrong. I found a valuable script on github (though for the life of me, I can’t seem to remember the name of the project) and here’s what I distilled it down to:

'use strict';
var AWS = require('aws-sdk'),
  crypto = require('crypto'),
  createS3Policy,
  getExpiryTime;

getExpiryTime = function () {
  var _date = new Date();
  return '' + (_date.getFullYear()) + '-' + (_date.getMonth() + 1) + '-' +
    (_date.getDate() + 1) + 'T' + (_date.getHours() + 3) + ':' + '00:00.000Z';
};

createS3Policy = function(contentType, subFolder, callback) {
  var s3Policy = {
    'expiration': getExpiryTime(),
    'conditions': [
      ['starts-with', '$key', subFolder],
      {'bucket': 'nba-agc'},
      {'acl': 'public-read'},
      ['starts-with', '$Content-Type', contentType]
    ]
  };
  // stringify and encode the policy
  var stringPolicy = JSON.stringify(s3Policy);
  var base64Policy = new Buffer(stringPolicy, 'utf-8').toString('base64');
  // sign the base64 encoded policy
  var signature = crypto.createHmac('sha1', process.env.AWS_SECRET_KEY)
    .update(new Buffer(base64Policy, 'utf-8')).digest('base64');
  // build the results object
  var s3Credentials = {
    s3Policy: base64Policy,
    s3Signature: signature,
    AWSAccessKeyId: process.env.AWS_ACCESS_KEY_ID
  };
  // send it back
  callback(s3Credentials);
};
app.get('/s3_policy', function(req, res) {
  createS3Policy(req.query.mimeType, req.query.subFolder, function (creds, err) {
    if (!err) {
      return res.send(200, creds);
    } else {
      return res.send(500, err);
    }
  });
});

To use this, I just issue a GET request of the form: http://localhost:3000/s3_policy?subFolder=folder_name&mimeType=image/png