authentication - Which headers do I have to pass on an JavaScript S3 AWS request using signature v4 and assumed role credentials? -


i'm trying make rest connection amazon s3 , i'm struggling implement signature v4 process. know, amazon provides javasscript sdk, need work myself.

to test code, i'm using aws testsuite , code returns expected results. however, real life attempts fail because of signature not match error.

the issue me is, examples don't include headers except host , date kind of straightforward. i'm having pass "full monty" including access tokens , i'm sure there problem headers.

here i'm doing on click of button:

function simples3scenario(my_storage) {   return new rsvp.queue()     .push(function () {       return my_storage.alldocs();     })     .push(function (my_alldocs_response) {       console.log("initial alldocs")       console.log(my_alldocs_response);     })     ... }; 

alldocs run this:

s3storage.prototype.buildquery = function (param, options) {   var context = this,     url = this._base_url,     url_path = this._bucket + "/",     headers,     requesttext;    return new rsvp.queue()     .push(function () {       return sigv4_custom.makesignedrequest(         "get",         url + url_path,         '',         {"max-key": 100, "prefix": "sample_folder"},         {},         context._region,         "s3",         "aws4-hmac-sha256",         context._secret_access_key,         context._access_key,         context._session_token       );     })     .push(function (e) {       console.log("yupi");       console.log(e);     })     ...    

which enters request signature handler, based on (not working signature v4) amazon example | code: sigv4.js:

(sorry, not shortened yet, scroll down entry point, work up)

  var sigv4_custom = new function(){     this.createcanonicalrequest = function(){};     this.createstringtosign = function(){};     this.generatesignatureandsign = function(){};     this.makesignedrequest = function(){};   }    // trim polyfill   string.prototype.trim = string.prototype.trim || function () {     var start = -1,       end   = this.length;      while( this.charcodeat(--end) < 33 );     while( this.charcodeat(++start) < 33 );      return this.slice( start, end + 1 );   };    // =============== generator funtions =================   // generate query parameter string canonical request   function generatecanonicalquerystring(my_parameter_dict) {     var canonical_query_string = '',        encoded_parameter_dict = {},       key_list = [],       key,       value,       i,       i_len;      // set , encode     (key in my_parameter_dict) {       if (my_parameter_dict.hasownproperty(key)) {         value = my_parameter_dict[key];          if (typeof value === "object") {           encoded_parameter_dict[encodeuricomponent(key)] =             encodeuricomponent(value[0]) + '&';            // append each additional value query parameter           (i = 0, i_len = value.length; < i_len; += 1) {             encoded_parameter_dict[encodeuricomponent(key)] +=               encodeuricomponent(key) + '=' + encodeuricomponent(value[i]) +'&';           }           encoded_parameter_dict[encodeuricomponent(key)] =             encoded_parameter_dict[encodeuricomponent(key)].slice(0,-1);         } else {           encoded_parameter_dict[encodeuricomponent(key)] =             encodeuricomponent(value);         }       }     }      // fill key_list     (key in encoded_parameter_dict) {       if (encoded_parameter_dict.hasownproperty(key)) {         key_list.push(key);       }     }      key_list.sort();     (i = 0, i_len = key_list.length; < i_len; += 1) {       canonical_query_string +=         key_list[i] + "=" + encoded_parameter_dict[key_list[i]] + "&";     }     return canonical_query_string.slice(0, -1);   }    // generate canonical header string   function generatecanonicalheaderstring(my_header_dict, is_signature) {     var canonical_header_string = '',       encoded_header_dict = {},       header_list = [],       header,       value,       trimmed_value,       header_lowercase,       i,       i_len,       separator,       connector,       format,       cutoff;      if (is_signature) {       cutoff = -1;       separator = ":";       connector = "\n";       format = function (my_value) {         return my_value.tolowercase();       }     } else {       cutoff = -1;       separator = "=";       connector = "&";       format = function (my_value) {         return my_value;       }     }      // take header keys , put in array, sort , build     (header in my_header_dict) {       if (my_header_dict.hasownproperty(header)) {         header_lowercase = format(header);         value = my_header_dict[header];         trimmed_value = undefined;          //xxx there not strings in headers...         if (value.trim) {           trimmed_value = value.trim();         }         if (encoded_header_dict[header_lowercase] === undefined) {           encoded_header_dict[header_lowercase] =  trimmed_value || value;           header_list.push(header_lowercase);         } else {           encoded_header_dict[header_lowercase] += "," + trimmed_value || value;         }       }     }     header_list.sort();     (i = 0, i_len = header_list.length; < i_len; += 1) {       canonical_header_string +=          header_list[i] +           separator +             encoded_header_dict[header_list[i]] +               connector;     }     canonical_header_string = canonical_header_string.slice(0, cutoff);     return canonical_header_string;   }    // generate signed header string   function generatesignedheaderstring(my_header_dict) {     var signed_header_string = '',        header_list = [],       header,       header_lowercase,       i,       i_len;      (header in my_header_dict) {       if (my_header_dict.hasownproperty(header)) {         header_list.push(header.tolowercase());       }     }     header_list.sort();     (i = 0, i_len = header_list.length; < i_len; += 1) {       signed_header_string += header_list[i] + ';';     }      return signed_header_string.slice(0, -1);   }    // returns timestamp in yyyymmdd't'hhmmss'z' format, sigv4 calls   function generatetimestamp() {     var date = new date();      function bump(my_time_parameter) {       if (my_time_parameter.length === 1) {         return '0' + my_time_parameter;       }       return my_time_parameter;     }      // assemble date, bump single digits doubles     // validation: return "20130524t000000z";     return date.getutcfullyear() +       bump((date.getutcmonth()+1).tostring()) + // month       bump(date.getutcdate().tostring()) + // day      't' +       bump(date.getutchours().tostring()) + // hour       bump(date.getutcminutes().tostring()) + // minute       bump(date.getutcseconds().tostring()) + // second       'z';   }    // generate credential scope   function generatecredentialscope(my_timestamp, my_region, my_service) {     return my_timestamp.substring(0, 8) + "/" +        my_region + "/" +       my_service + "/" +       "aws4_request";   }    // ================== core methods ==================   sigv4_custom.createstringtosign = function (request_time, credential_scope,     canonical_request, signing_algorithm) {      // step 1: designate algorithm (for sigv4 sha256)     // step 2: designate requestdate (already done, passed function)     // step 3: create credentialscope (already done, passed funtion)     return signing_algorithm + '\n' +      request_time + '\n' +      credential_scope + '\n' +      canonical_request;   }    sigv4_custom.generatesignatureandsign = function(secret, request_time, region,     service, string_to_sign) {     var datestamp = request_time.substring(0, 8),         hash_date,         hash_region,          hash_service,         hash_signing,         request = 'aws4_request';      hash_date = cryptojs.hmacsha256(datestamp, 'aws4' + secret, {asbytes: true});     hash_region = cryptojs.hmacsha256(region, hash_date, {asbytes: true});     hash_service = cryptojs.hmacsha256(service, hash_region, {asbytes: true});     hash_signing = cryptojs.hmacsha256(request, hash_service, {asbytes: true});      // sign , return     return cryptojs.hmacsha256(string_to_sign, hash_signing)       .tostring(cryptojs.enc.hex);   }    sigv4_custom.createcanonicalrequest = function(method, pathname,     parameter_dict, header_dict, hashed_payload) {     var canonical_request = "",         http_request_method = "",         canonical_url = "",         canonical_query_string = "",         canonical_header_string = "",         signed_header_string = "",         payload;      // step 1: start http request method     http_request_method = method;      // step 2: add canonicalurl parameter     canonical_url = pathname;      // step 3: add canonicalquerystring parameter     canonical_query_string = generatecanonicalquerystring(parameter_dict);      // step 4: add canonicalheaders parameter     canonical_header_string = generatecanonicalheaderstring(header_dict, true);      // step 5: add signedheaders parameter     signed_header_string = generatesignedheaderstring(header_dict);      // step 6: add hashed payload     payload = hashed_payload;      // step 7: string canonicalrequest steps 1 through 6     canonical_request += http_request_method + '\n' +       canonical_url + '\n' +       canonical_query_string + '\n' +       canonical_header_string + '\n\n' +       signed_header_string + '\n' +       payload;      return canonical_request;   };    // =================== entry point ===================   // call function make sigv4 rest api call.    sigv4_custom.makesignedrequest = function (method, path, payload,     parameter_dict, header_dict, region, service, signing_algorithm,     secret_access_key, access_key_id, security_token) {      var link = document.createelement("a"),         request_time = generatetimestamp(),         scope = generatecredentialscope(request_time, region, service),         authorization_string,         canonical_request,         string_to_sign,         request_uri,         signature;      // link location object, set href use properties     link.href = path;      // set headers, generate canonical_request     // payload must hashed here, may vary , hash required     // canonization , header. empty payloads hash empty "".     header_dict['x-amz-content-sha256'] = cryptojs.sha256(payload)       .tostring(cryptojs.enc.hex);     header_dict['host'] = link.hostname;     header_dict['x-amz-date'] = request_time;     header_dict['x-amz-credential'] = access_key_id + "/" + scope;     header_dict['x-amz-security-token'] = security_token;     header_dict['x-amz-algorithm']  = signing_algorithm;     header_dict['x-amz-expires'] = 86400;      // task 1: compute canonical request     canonical_request = cryptojs.sha256(       this.createcanonicalrequest(         method,         link.pathname,         parameter_dict,         header_dict,         header_dict['x-amz-content-sha256']       )     )     .tostring(cryptojs.enc.hex);      // delete host because in headers (needs in both      // create canonicalization)     delete parameter_dict['host'];      // task 2: create string sign using encoded canonical request     string_to_sign = this.createstringtosign(       request_time,       scope,       canonical_request,       signing_algorithm     );      // task 3: create signature using signing key , string sign     signature = this.generatesignatureandsign(       secret_access_key,       request_time,       region,       service,       string_to_sign     );      // task 4: build authorization header     header_dict['authorization'] = header_dict['x-amz-algorithm'] +       " credential=" + header_dict['x-amz-credential'] + "," +         "signedheaders=" + generatesignedheaderstring(header_dict) + "," +           "signature=" + signature;      // task 5: make request (through jio)     return new rsvp.queue()       .push(function () {         return jio.util.ajax({           "method": method,           "url": path,           "headers": header_dict         });       });   } 

so when run amazon samples 2 headers through this, correct signature , authorization header @ end. believe i'm doing wrong headers, headers should go signature, can't find online , stuck on few days now.

question:
maybe has idea looking @ how i'm handling headers, why requests aws fail due non-matching signature?

thanks!

edit:
have used amazon example page deriving signatures. if run sample inputs through createsignatureandsign method, can produce same outputs. signature correct secret correct.


Comments

Popular posts from this blog

shopping cart - Page redirect not working PHP -

php - How to modify a menu to show sub-menus -

python - Installing PyDev in eclipse is failed -