Amazon S3 - ERR_INSECURE_RESPONSE

1.4k Views Asked by At

This question has already been asked here but that answer didn't help me as I know that the URL is correct as it points to a US Standard url as detailed in the amazon guide here

So I'm attempting to upload a file to my bucket via the angular library ng-file-upload. I believe that I've setup the bucket correctly:

  • The buckets name is ac.testing
  • The CORS configuration for this:

    <?xml version="1.0" encoding="UTF-8"?>
      < CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
      < CORSRule>
        < AllowedOrigin>*</AllowedOrigin>
        < AllowedMethod>POST</AllowedMethod>
        < AllowedHeader>*</AllowedHeader>
      < /CORSRule>
    < /CORSConfiguration>
    

I had to put a space after the opening brackets above as SO didn't let me add it if I didn't.

I've understood this as allow POSTS from any location regardless of heading - is that correct?

And my policy which I generated:

{
    "Version": "2012-10-17",
    "Id": "Policy<numbers>",
    "Statement": [
        {
            "Sid": "Stmt<numbers>",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::ac.testing/*"
        }
    ]
}

Finally - in my actual code that attempts to upload:

      var policy = {
        "expiration": "2020-01-01T00:00:00Z",
        "conditions": [
          {"bucket": "ac.testing"},
          ["starts-with", "$key", ""],
          {"acl": "private"},
          ["starts-with", "$Content-Type", ""],
          ["starts-with", "$filename", ""],
          ["content-length-range", 0, 524288000]
        ]
      }

      var uploadDetails = {
        url: 'https://ac.testing.s3.amazonaws.com/',
        method: 'POST',
        data: {
          key: file.name, 
          acl: 'public-read', 
          // application/octet-stream is the default format used by S3
          'Content-Type': file.type != '' ? file.type : 'application/octet-stream', 
          AWSAccessKeyId: '<my-access-key-id>',
          policy: policy, 
          signature: '<my-access-signature>',
          filename: file.name, 
        },
        file: file
      };


      if (file) {
        // Upload to Amazon S3
        file.upload = Upload.upload(uploadDetails).then(function(success) {
          console.log(JSON.stringify(success) );
        },function(error) {
          console.log(error);
        },function(progress) {
          console.log(JSON.stringify(progress) );
        });
      }  

So where am I going wrong here?

EDIT

A couple of things that I wasn't doing was encoding the policy and the signature according to Base64 encoding.

That process involves encoding your policy and then using that generated code, along with your AWS Secret Access Key to generate an SHA-1 HMAC code. Even after this it still returns the same error.

I also added another Permission for the bucket. It matches the policy and CORS settings already defined here but is defined as everyone:

Permission

EDIT 2

I created a new bucket called ac-k24-uploads and updated the url to match this:

uploadDetails = {
    url: 'https://ac-k24-uploads.s3.amazonaws.com/',

Now the error coming back is this:

enter image description here

EDIT 3

Looking around it seems that headers that amazon doesn't like are being added to the request. I tried it on ng-file-uploads and it works but on my own machine it doesn't. The fix for this seems to be removing these headers like so:

method: 'POST',
  headers: {
    'Authorization': undefined
  },

but I still get the same error. Why are these headers being attached to this request?

EDIT 4

Even with the code above the headers were still getting added at a different place so I located it and remove them. The error which I recieve now is this:

enter image description here

2

There are 2 best solutions below

0
On BEST ANSWER

The actual problem was two fold:

  • The headers were incorrect as the "Authorization" header was still present even after deleting it from the Upload.upload portion of the code. To fix this I had to delete the object from my api.injector code - this was where it was being added.

    delete config.headers['Authorization']
    
  • Following on from EDIT3 the signature that I generated was wrong - so I had to regenerate it.

Thanks to Michael for the help.

2
On

This is not related to CORS.

It is because of the dot in the name of your bucket.

If your bucket is indeed in US-Standard (example-bucket.s3.amazonaws.com is not necessarily a "US Standard" URL) then this is what you need:

var uploadDetails = { url: 'https://s3.amazonaws.com/ac.testing/', ...

This is referred to as the path-based or path-style URL where the bucket is expressed as the first element of the path, rather than as including it in the hostname.

This is necessary if the bucket name has a dot, and s3. needs to be s3-region. for buckets not in US Standard.

This is a limitation of wildcard SSL/TLS certificates. S3 presents a certificate valid for *.s3[-region].amazonaws.com and the rules for such certificates state that * cannot match a dot... therefore the certificate is considered invalid and therefore it's an "insecure response."

Or, just create a bucket with a dash instead of a dot, and your code should work as-is.

Since you are using Signature V2, either hostname construct results in an identical signature for an otherwise-identical request. Not true for Sig V4.