bettiolo / oauth-signature-js

JavaScript OAuth 1.0a signature generator (RFC 5849) for node and the browser
https://www.npmjs.com/package/oauth-signature
BSD 3-Clause "New" or "Revised" License
232 stars 71 forks source link

Parameters treatment #10

Open jmendiara opened 9 years ago

jmendiara commented 9 years ago

The url used for calculating the signature must be the same you are using in the final GET. When one of the parameters is an array, there are several approaches to serialize it to a string, and the backend dictates how an array should be serialized examples:

var params = { 
 arr: [1,2]
};
//With commas: arr=1,2
//duplicate params: arr=1&arr=2
//be explicit: arr[0]=1&arr[1]=2
//be explicit: arr=[1,2]

oauth-signature-js is using in their computation the "duplicate params" approach, and there is no easy way to override it.

The workaround is passing the parameters for your module always as strings, solving this level of customization outside your module (also solves #9). In fact, is how your online example works, always giving string parameters.

Maybe stating this in the README.md will help devs to understand this problem and the easiest solution

jmendiara commented 9 years ago

Some URL parameters serializers (from js objects to querystring) are not including parameter keys in the querystring if their values are null or undefined. You are forcing that value to be the empty string, including the key in the url used to generate the signature

var obj = {
  foo: 'bar',
  nullable: null
};

//you are using: foo=bar&nullable=
//serializers may use: foo=bar

Other thing is the boolean treatment: A true boolean means including only the key, and false boolean to not include it?

var obj = {
  foo: 'bar',
  secure: true,
  xbar: false
};

//you are using: foo=bar&secure=true&xbar=false (when pr#9 is accepted)
//serializers may use: foo=bar&secure
jmendiara commented 9 years ago

Proposal: Let the user to specify the querystring to perform the signature

bettiolo commented 9 years ago

Hi @jmendiara,

The OAuth RFC is based on parameters and not query strings, the signature base string is made of three parts and the last one is a concatenation of the parameters where the duplicated parameters must be concatenated using the "duplicate params" approach.

This is a relevant example from the RFC on how to handle duplicated parameter names: http://oauth.net/core/1.0a/#rfc.section.9.1.1

The three parts of a signature are HTTP_METHOD&URL&PARAMETERS, as you can see it is not a url + querystring, this is the relevant section from the RFC: http://oauth.net/core/1.0a/#rfc.section.9.1.3

You need to consider that the way you serialize parameters in query string is different than how you generate the signature base string. You don't blindly put the querystring in the last part of the signature base string, you need to follow the spec on how to concatenate them accordingly.

Parameters without a value must be concatenated to the signature base sting:

Parameters are concatenated in their sorted order into a single string. For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61), even if the value is empty. Each name-value pair is separated by an '&' character (ASCII code 38).

I know that the signature base string's parameters part can be confusing as it looks like the query string but the rules on how to serialize it are pretty strict. If I don't follow this convention, the servers following the specification will fail to validate the signature.

Does this clarify the situation?

jmendiara commented 9 years ago

Then, if one server only accepts the comma-separated format for an array GET http://foo.com/bar?arr=1,2&oauth1stuff

and the client code manages internally

params = {
 arr: [1,2]
}

When the client app wants to use your module, it has to convert to

var convertedParams = {
  arr:  params.arr.join(',')
};
oauthSignature.generate(..., convertedParams, ....);

to bypass your internal default parameter serialization. Hey! It's OK for me!!! Is how I'm using it, indeed.

PS: Readme clarification would be nice ;)

jmendiara commented 9 years ago

http://oauth.net/core/1.0a/#rfc.section.9.1.1 talks about duplicated parameters, it's not talking about how you serialize arrays in the javascript client side, which was my intention when opening the issue.

When the array serialization (converting a javascript array to a set of parameters) is done using duplicate names, you should do as per 9.1.1 section.

DYKWIM?