Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, October 1, 2016

SignatureDoesNotMatch $cordovaFileTransfer

SignatureDoesNotMatch $cordovaFileTransfer


I'm trying to upload a video to Amazon s3 previously recorded with $cordovaCapture.

The capture process works correctly, and as a response I get the object:

[MediaFile]    0:       MediaFileend: 0      fullPath: "file:/storage/sdcard/DCIM/Camera/VID_20160919_144041.mp4"      lastModified: null      lastModifiedDate: 1474288843000      localURL: "cdvfile://localhost/persistent/DCIM/Camera/VID_20160919_144041.mp4"      name: "VID_20160919_144041.mp4"      size: 17098      start: 0      type: "video/mp4"      __proto__: utils.extend.F    length: 1    __proto__: Array[0]  

Then, before I upload the video, I request to my server the Authenticating URL as it follows:

nodeJS

getSignedUrl: function (filename, type, callback) {    if (filename) {      AWS.config.update({        accessKeyId: 'my_access_key',        secretAccessKey: 'my_secret_access_key',        region: 'my_region'      });        var s3 = new AWS.S3();      s3.getSignedUrl('putObject', {Bucket: 'my_bucket', Key: 'uploads/' + filename, ContentType: type}, function (err, url) {        if (err) {          callback(err);        } else {          callback(url);        }      });    } else {      callback('Error');    }  }  

That gives me the next endpoint:

https://s3-my_region.amazonaws.com/my_bucket/uploads/VID_20160919_144?=video%2Fmp4&Expires=1474289746&Signature=sF67ukPu3oELJXzsmAXCeeEJ%2FE4%3D  

After I get the URL to point my upload, here is where problems are comming:

Having this code:

var options = {    httpMethod: "PUT",    fileName: name,    mimeType: type,    chunkedMode: 'false',    encodedURI: 'false',    headers: {      "Content-Type": type    }  };    $cordovaFileTransfer.upload(url, videoPath, options)    .then(function (result) {      callback(result);    }, function (err) {      callback(err);    }, function (progress) {      p = progress;  });  

This is the error that I get:

http status: 403  Code: 1  description:       SignatureDoesNotMatch    The request signature we calculated does not match the signature you provided. Check your key and signing method.    my_access_key          PUT      video/mp4      1474291133      /my_bucket/uploads/VID_20160919_150347.mp4              nwLEVBOarxi7YwyB4hJ2op4j1ms%253D              50 55 54 0a 0a 76 69 64 65 6f 2f....        CC29DD761826BAFF          OHTLyBaAa29X04msYXqwmvr1Mw90wnPmkxXeU7pTOb9pFwDuuRXDC3AdLNwVIoEHnoUEsceWn24=        

Sounds like the problem is around the header, that doesn't work as expected.

As well, I tried with a second option code in my client following directly the documentation of the cordova-plugin-file-transfer:

var options = new FileUploadOptions(),    ft = new FileTransfer();    options.httpMethod = "PUT";  options.fileName = name;  options.mimeType = type;  options.headers = {    ContentType: type  };  options.chunkedMode = "false";  options.encodeURI = "false";    ft.upload(videoPath, url, callback, callback, options);  

with the same response error.

Here I got also problems with Content-Type. Even though in the documentation declares like:

var headers = {    "Content-Type": 'video/mp4'  };    options.headers = headers;  

it was returning me the next error:

http status: 501  description:       NotImplemented          A header you provided implies functionality that is not implemented        
Transfer-Encoding
231F38AFFBB587C6 . . .

Although I'm gonna keep investigating... could someone help me with this problem?

just as a note, I made it work with a $http.post like in this other post of mine.

Thanks in advice.

UPDATE

Investigating much more in the issue, with the nodeJS code I wasn't able to upload anything as well, so I just modified the S3 constructor like this way:

s3 = new AWS.S3({    signatureVersion: 'v4',    region: "us-west-2"  });  

After that, checking with curl through console like this way:

curl -v -H "Content-Type: application/octet-stream" --upload-file "/Users/my_user/Desktop/VID_20160920_233443.mp4" "https://s3-us-west-2.amazonaws.com/my_bucket/uploads/VID_20160920_233443.mp4?Content-Type=video%2Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJV3UP7LBEKPYMLGA%2F20160921%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160921T103723Z&X-Amz-Expires=600&X-Amz-Signature=8463625a45237452280b3dc9cfd89366093f7b78f8c76598ba2240f06c7f20c9&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read"  

the response was successfully:

*   Trying 54.231.176.22...  * Connected to s3-us-west-2.amazonaws.com (54.231.176.22) port 443 (#0)  * TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256  * Server certificate: *.s3-us-west-2.amazonaws.com  * Server certificate: DigiCert Baltimore CA-2 G2  * Server certificate: Baltimore CyberTrust Root  > PUT /my_bucket/uploads/VID_20160920_233443.mp4?Content-Type=video%2Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJV3UP7LBEKPYMLGA%2F20160921%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160921T103723Z&X-Amz-Expires=600&X-Amz-Signature=8463625a45237452280b3dc9cfd89366093f7b78f8c76598ba2240f06c7f20c9&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read HTTP/1.1  > Host: s3-us-west-2.amazonaws.com  > User-Agent: curl/7.43.0  > Accept: */*  > Content-Type: application/octet-stream  > Content-Length: 18964  > Expect: 100-continue  >   < HTTP/1.1 100 Continue  * We are completely uploaded and fine  < HTTP/1.1 200 OK  < x-amz-id-2: moDxOsEISsfqjCILaIsJtl3ncc7UeH4hNNISiJeuH46MrDrHEfVm9EKC5RRkORMilDEE5z7l8cI=  < x-amz-request-id: BC345E2AC71AC019  < Date: Wed, 21 Sep 2016 10:38:05 GMT  < x-amz-expiration: expiry-date="Fri, 23 Sep 2016 00:00:00 GMT", rule-id="Delete bad uploads after 1 day"  < ETag: "7688c487b1ea40c849fdb070cf736b28"  < Content-Length: 0  < Server: AmazonS3  <   * Connection #0 to host s3-us-west-2.amazonaws.com left intact  

changing the angular code like this new one:

var options = new FileUploadOptions(),      ft = new FileTransfer();    options.httpMethod = "PUT";  options.fileKey = "file";  options.fileName = name;  options.mimeType = type;  options.chunkedMode = false;    options.headers = {    "Content-Type": type,    "x-amz-acl": 'public-read'  };    ft.upload(videoPath, url, callback(null), callback, options);  

The problem still comes:

An error has occurred: Code = 1  upload error source cdvfile://localhost/persistent/DCIM/Camera/VID_20160921_122323.mp4  upload error target https://s3-us-west-2.amazonaws.com/my_bucket/uploads/VID_20160921_122?9e365af3f771c5d&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read  http status: 501  description:   NotImplementedA header you provided implies functionality that is not implemented
Transfer-Encoding
D646593FD109C0F8wVmGWPAAWdmSXdq5N/eO7ihqHk0GoMlXNe6k9sAyyEz55Q4k2gGgkgsgyXkh8xsxUDlmzQdAIPQ=

Here I include my FileUploadOptions():

chunkedMode: false  fileKey: "file"  fileName: "VID_20160921_125152.mp4"  headers: Object    Content-Type: "video/mp4"    x-amz-acl: "public-read"    __proto__: Object  httpMethod: "PUT"  mimeType: "video/mp4"  params: null  

UPDATE 2

Trying directly with the $cordovaFileTransfer plugin from ngCordova, I get another error:

"  AuthorizationQueryParametersErrorError parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting "/YYYYMMDD/REGION/SERVICE/aws4_request".C863350E96804F5C7TmXBDlsGNvDmLFKgLePTMAg+Onf8y1ZPTEWmbdHPAyWHFIdt1+5J7U3H8Ygnf3sebMRpRNdxXA="  

UPDATE 3

To clarify everything as much as possible I've deployed a github with all the backend/frontend in which I'm working.

Thanks once again.

UPDATE 4

Thanks to the help of daserge, I could get the headers of my PUT. Here bellow I paste the result:

HTTP/1.1 400 Bad Request  x-amz-request-id    3F686CFD09B5C6DD  x-amz-id-2  KDrmvzhnrWfLB+Tdttg88MaPVOp2LOBAhwEqiBR0XdMpaje3lRsiM6mHfjv5ULzD7GweiT9C2T0=  Content-Type    application/xml  Date    Sat, 24 Sep 2016 17:00:03 GMT  Server  AmazonS3  Transfer-Encoding   chunked  Proxy-Connection    Close    PUT /my_bucket/uploads/VID_20160924_190000.mp4?Content-Type=video%252Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJV3UP7LBEKPYMLGA%252F20160924%252Fus-west-2%252Fs3%252Faws4_request&X-Amz-Date=20160924T170002Z&X-Amz-Expires=600&X-Amz-Signature=ca3c992290bdf51e14bab6d67e4c520b280368bdd2a0274b552dc3e975f55c9d&X-Amz-SignedHeaders=host%253Bx-amz-acl&x-amz-acl=public-read HTTP/1.1  Content-Type    application/octet-stream  Content-Length  56116  User-Agent  Dalvik/2.1.0 (Linux; U; Android 5.0; Aquaris E5 HD Build/LRX21M)  Host    s3-us-west-2.amazonaws.com  Connection  Keep-Alive  Accept-Encoding gzip  

Then I realiced there were 2 parameters wrong:

Content-Type: application/xml  Transfer-Encoding: chunked  

As well, I've realiced about encoding. It sould be %2F and it's coming like %252F.

Which is strange because the way I'm using the params seems to be right:

options = {    fileKey: 'file',    fileName: name,    chunkedMode: false,    httpMethod: 'PUT',    mimeType: "application/octet-stream",    headers: {      "Content-Type": "application/octet-stream"    }  };    $cordovaFileTransfer.upload(server, filePath, options)    .then(function (result) {      console.log(result);    }, function (err) {      console.log(err);    }, function (progress) {      console.log(progress);    });  

as well, thanks to bvakiti I've realiced there is an error message because I'm sending the video to an https. I'm trying http.

Answer by Akul Narang for SignatureDoesNotMatch $cordovaFileTransfer


I guess there is some problem with derivation of Access Key from AWS.

Try Using this:

function getSignatureKey(key, dateStamp, regionName, serviceName) {      var kDate= Crypto.HMAC(Crypto.SHA256, dateStamp, "AWS4" + key, { asBytes: true})      var kRegion= Crypto.HMAC(Crypto.SHA256, regionName, kDate, { asBytes: true });      var kService=Crypto.HMAC(Crypto.SHA256, serviceName, kRegion, { asBytes: true });      var kSigning= Crypto.HMAC(Crypto.SHA256, "aws4_request", kService, { asBytes: true });        return kSigning;  }  

http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-jscript

I also found an old blog if it helps:

http://coenraets.org/blog/2013/09/how-to-upload-pictures-from-a-phonegap-app-to-amazon-s3/

Answer by kuzyn for SignatureDoesNotMatch $cordovaFileTransfer


Could be a problem with uploading with an empty body / empty Content-Length

Have a look at this thread: https://github.com/aws/aws-sdk-js/issues/15

Answer by Sachin for SignatureDoesNotMatch $cordovaFileTransfer


After updating your AWS bucket configuration do not pass the parameters when creating S3 object. Try below code.

   // make managed upload      var upload = new AWS.S3.ManagedUpload({          params: metadata      });        var s3Head = new AWS.S3();  

Make changes in routes/endpoints.js.

Answer by bvakiti for SignatureDoesNotMatch $cordovaFileTransfer


I faced an issue of error code 1 during fileTransfer and giving html elements as response.

Problem is with SSL connection. Try giving http and not https in the server url, It will work fine. But when it comes to authentication you will have change in backend. There is no problem with cordovaFileTransfer.

Hope this helps.

Answer by user3728134 for SignatureDoesNotMatch $cordovaFileTransfer


It seems that there is a conflict between the endpoint you get from AWS and the way you use $cordovaFileTransfer.

When you get the endpoint with s3.getSignedUrl in your server, only the params of the the response URL are encoded (the base URL keeps non-encoded).

When you use $cordovaFileTransfer That function encodes again the params, that's why you see that %252F which match to //.

There are 3 options:

  • Instead, before your $cordovaFileTransfer calling, decode the params

    var host = server.split('?')[0] + '?' + decodeURIComponent(server.split('?')[1]);  
  • Use options.params as described in the documentation

The option encodeURI: false suggested in other help comments didn't work for me

Hope it helps.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.