title: Amazon S3 POST api, and signing a policy with NodeJS
body: <p>I'm trying to get an built that allows users to upload a file directly to my Amazon S3 bucket, from a NodeJS powered website. It seems the only tutorials out there, other than <strong><a href="http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html">the actual amazon docs for this</a></strong> are all very out of date. </p>
  
  <p>I've been following <strong><a href="http://blog.tcs.de/post-file-to-s3-using-node/">this tutorial</a></strong>, for the basic info, but again it's out dated. It doesn't have the method calls to <code>crypto</code> correct, as it tries to pass a raw JavaScript object to the <code>update</code> method, which throws an error because it's not a string or buffer.</p>
  
  <p>I've also been looking at the source for <strong><a href="https://github.com/LearnBoost/knox/blob/master/lib/auth.js">the knox npm package</a></strong>. It doesn't have POST support built in - which I totally understand, because it's the browser doing the POST once it has the right fields. Knox does appear to have the right code to sign a policy, and I've tried to get my code working based on this... but again to no avail.</p>
  
  <p>Here is what I've come up with, for code. It produces a base64 encoded policy, and it creates a signature... but it's the wrong signature according to Amazon, when I try to do a file upload.</p>
  
  <pre><code>
  var crypto = require("crypto");
  var config = require("../../amazonConfig.json");
  
  exports.createS3Policy = function(callback) {
    var date = new Date();
  
    var s3Policy = {
      "expiration": "2014-12-01T12:00:00.000Z",
      "conditions": [
        {"acl": "public-read"}, 
        ["content-length-range", 0, 2147483648],
        {"bucket": "signalleaf"}, 
        ["starts-with", "$Cache-Control", ""],
        ["starts-with", "$Content-Type", ""],
        ["starts-with", "$Content-Disposition", ""],
        ["starts-with", "$Content-Encoding", ""],
        ["starts-with", "$Expires", ""],
        ["starts-with", "$key", "/myfolder/"], 
        {"success_action_redirect": "http://example.com/uploadsuccess"},
      ]
    };
  
    var stringPolicy = JSON.stringify(s3Policy).toString("utf-8");
    var buffer = Buffer(stringPolicy, "utf-8");
  
    var encoded = buffer.toString("base64");
    var signature = crypto.createHmac("sha1", config.secretKey)
      .update(new Buffer(stringPolicy, "utf-8")).digest("base64");
  
  
    var s3Credentials = {
      s3PolicyBase64: encoded,
      s3Signature: signature
    };
  
    GLOBAL.s3creds = s3Credentials;
  
    callback(s3Credentials);
  };
  
  </code></pre>
  
  <p>I'm obviously doing something wrong, here. But I have no idea what. Can anyone help identify what I'm doing wrong? Where my problem is? <strong>Does anyone have a working tutorial for how to generate a proper Amazon S3 Policy, with signature, from NodeJS v0.10.x, for a POST to the s3 REST api?</strong></p>