|
Replies:
37
-
Pages:
3
[
1
2
3
| Next
]
-
Last Post:
Jul 27, 2009 3:46 AM
by: Brandon Checketts
|
|
|
Posts:
71
Registered:
2/8/06
|
|
|
|
signature authentication with JavaScript?
Posted:
May 8, 2009 9:21 PM PDT
|
|
|
My application uses just HTML forms, JavaScript, and XSLT. That's it. Is there any way to produce signatures for authentication with this combination? Or has Amazon just destroyed my app, developed over years and used by over 5,000 visitors a week?
Aaron
|
|
Posts:
2,578
Registered:
2/8/06
|
|
|
Posts:
11
Registered:
4/17/07
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 7:33 AM PDT
in response to: Jim L Taylor
|
|
|
I'm in the same boat, I have javascript widgets that use the Product Advertising API. However, building the signature with Javascript isn't something I'm planning on doing. To quote the documentation:
IMPORTANT:
Your Secret Access Key is a secret, and should be known only by you and AWS. You should never include your Secret Access Key in your requests to AWS. You should never e-mail your Secret Access Key to anyone. It is important to keep your Secret Access Key confidential to protect your account.
Since JS code is open to anyone for viewing, it's impossible to keep the key hidden from prying eyes. Therefore, it will be necessary to route ALL calls through a web server instead.
I know, "ouch!".
Andy
|
|
Posts:
194
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 1:20 PM PDT
in response to: Aaron Shepard
|
|
|
Assuming the use of an already working REST query (generally the case with a retro-fit), I came up with the following:
function fnSignedQuery( strQuery, strKey ) {
strQuery += "&Timestamp=" + timestamp();
var strSignedQuery;
var strToSign = strQuery.replace( /(https?:\/\/)([^\/]*)(\/.*)\?(.*)/i,
function( strMatch, strScheme, strHost, strUri, strParams ) {
var aParams = strParams.split("&").sort();
for ( var i in aParams ) {
var aKV = aParams[i].split("=");
for ( var j in aKV )
aKV[j] = encodeURIComponentAWS( aKV[j] );
aParams[i] = aKV.join("=");
}
strParams = aParams.join("&");
strHost = strHost.toLowerCase();
strSignedQuery = strScheme + strHost + strUri + "?" + strParams;
return (new Array( "GET", strHost, strUri, strParams )).join("\n");
})
strSignature = encodeURIComponentAWS( Base64.encode( HMAC_SHA256_MAC( strKey, strToSign ) ) );
strSignedQuery += "&Signature=" + strSignature;
return strSignedQuery;
}
function encodeURIComponentAWS( str ) {
// developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Functions/EncodeURIComponent
// "... encodeURIComponent escapes all characters except the following: alphabetic, decimal digits, - _ . ! ~ * ' ( ) ..."
// same for MS JScript ? seems to be.
return fnTranslate( encodeURIComponent( str ),
[ ["!", "%21"], ["39;", "%27"], ["(", "%28"], [")", "%29"], ["*", "%2A"] ] );
}
function fnTranslate( str, aTranslate ) {
for ( var i in aTranslate )
str = str.replace( aTranslate[i][0], aTranslate[i][1] );
return str;
}
function timestamp() { return toZString( new Date() ) }
function toZString( dt ) {
// "Sun, 10 May 2009 18:45:50 UTC" to "2009-05-10T18:45:50Z":
return dt.toUTCString().replace( /.{3}, (\d{2}) .{3} (\d{4}) (\d{2}:\d{2}:\d{2}) UTC/,
function(strMatch, strDay, strYear, strTime) {
strMonth = (dt.getUTCMonth()+1).toString().replace( /^(\d)$/, "0$1" );
return strYear + "-" + strMonth + "-" + strDay + "T" + strTime + "Z";
});
}
|
This uses
http://point-at-infinity.org/jssha256/ for the HMAC SHA256 and
http://www.webtoolkit.info/ for the Base64.
BUT - the signature isn't accepted by Amazon. Not sure why, all the intermediate steps check out as far as I can tell. Maybe an extra set of eyes can spot something, then we all can benefit.
Thanks !
|
|
Posts:
71
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 4:24 PM PDT
in response to: C. Sowa
|
|
|
FractalNavel, I'm too much of a novice at JavaScript to be able to follow most of this, but I noticed you're trying to construct your own timestamp. Isn't there a timestamp function in JavaScript that returns a complete one automatically?
Aaron
|
|
Posts:
2,578
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 4:58 PM PDT
in response to: C. Sowa
|
|
|
I assume you've double checked the result of the sort? Maybe post the strToSign value prior to its submission for hashing. That might help one of us see the problem.
Jim
|
|
Posts:
194
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 5:09 PM PDT
in response to: Aaron Shepard
|
|
|
... Isn't there a timestamp function in JavaScript that returns a complete one automatically?
Not the way you're thinking of, no. The AWS "Timestamp" parameter just contains a particular string representation of a datetime (
http://en.wikipedia.org/wiki/ISO_8601 ). JavaScript doesn't associate any special meaning with this. It also does not have a native "toString" implementation for this format, nor provides the ability to specify an arbitrary format string like many (most?) other languages.
I've rolled-my-own script for this in different ways over the years. I'm sure there are libraries & one-off functions out there that handle this in various ways that you could use instead. I just used what i had available.
General JavaScript docs at
https://developer.mozilla.org/en/JavaScript,
http://msdn.microsoft.com/en-us/library/yek4tbz0(VS.85).aspx.
|
|
Posts:
194
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 5:16 PM PDT
in response to: Jim L Taylor
|
|
|
With redactions:
GET
ecs.amazonaws.com
/onca/xml
AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&AssociateTag=XXXXXXXXXXXXXXXX&ListId=XXXXXXXXXXXXX&ListType=WishList&Operation=ListLookup&ProductPage=1&ResponseGroup=ListInfo&Service=AWSECommerceService&Sort=DateAdded&Timestamp=2009-05-11T00%3A12%3A46Z&Version=2007-10-29
|
|
|
Posts:
2,578
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 7:40 PM PDT
in response to: C. Sowa
|
|
|
That looks fine and when I replace the XXXX's with my info and run it through my function it works fine.
Hmmmmmmmmmmm....I see you are send the "strToSign" for the Hashing but I don't see where that variable is being sorted and formatted per the requirements. I mean, I do see these activities taking place but never being assigned to that variable.
I'm not java expert so I may must be overlooking the changes.
Jim
|
|
Posts:
194
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 10, 2009 8:39 PM PDT
in response to: Jim L Taylor
|
|
|
strToSign assignment: It's all done in the code block starting "var strToSign = strQuery.replace( ...". The regular expression breaks up the original query, and the replacement function canonicalizes the parameters, constructs & returns the string to be signed, and generates everything in the result query except the signature parameter.
By "works fine", you mean the sample I provided signs properly and is accepted by Amazon, when you use a working encoding function - ? Which would imply that one or more of the URI, Base64 or HMAC-SHA256 encoding functions that I use isn't working properly. That would be bad, since I'm relying on the work of others there. I've tried several alternatives for Base64, none fixed things - which in itself didn't prove anything.
I guess I'll have to compare encoding detail between this and a working example in a different language. Turning into more work than I had hoped, and it's still only shots in the dark. It looks like it
should
work. And I'm not completely confident that there's nothing undocumented going on over at Amazon that may be affecting the success of this approach, perhaps in conjunction with some quirk of the specific query that I've been using.
|
|
Posts:
2,578
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 11, 2009 6:07 AM PDT
in response to: C. Sowa
|
|
|
Okay. I see it now. The "function" is a parameter.
In C# I had to use byte arrays to pass to the hashing function. I assume the Java solution is different?
Yes. When I provided valid info in place of the X's and use the Hashing function I posted (C# solution) I can submit the request and get a valid response.
What is the length of the signature that is being returned?
Jim
|
|
Posts:
71
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 11, 2009 9:29 AM PDT
in response to: Jim L Taylor
|
|
|
Jim, for the sake of clarity, it's not Java. Despite the name, JavaScript has no relation to Java.
Aaron
|
|
Posts:
2,578
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 11, 2009 9:56 AM PDT
in response to: Aaron Shepard
|
|
|
I know. I apologize for the poor choice of wording in my response.
Do you see what might be causing the problem?
Jim
|
|
Posts:
194
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 11, 2009 11:58 AM PDT
in response to: Jim L Taylor
|
|
|
... In C# I had to use byte arrays to pass to the hashing function. I assume the Java solution is different? ... What is the length of the signature that is being returned?
Ah, hints - just what I was looking for. On my agenda today was to take a closer look at the UTF-8 encoding and related stuff. That jssha256.js that I'm using returns a string of hex characters
representing
the hash bytes - not quite what I need. What I need instead is to Base64 encode those bytes directly. Looks like I need to modify one or both of those third party routines to get what I want. That's not nearly as portable a solution as I had hoped for.
I'll re-post here when I've got this taken care of, hopefully working, or at the next obstacle.
Thanks again for the feedback.
|
|
Posts:
2,578
Registered:
2/8/06
|
|
|
|
Re: signature authentication with JavaScript?
Posted:
May 11, 2009 12:29 PM PDT
in response to: C. Sowa
|
|
|
Glad to hear my fumbling around was helpful...
Jim
|
|
|