views:

314

answers:

3

I have written an Service Provider implementation for OAuth and one of the Devs found a bug in the way the implementation was ordering query parameters. I totally missed the lexicographical ordering requirement in the OAuth spec and was just doing a basic string sort on the name value parameters

Given the following URI request from the consumer:

http://api.com/v1/People/Search?searchfor=fl&[email protected]&Include=addresses

The resulting signature base should order the parameters as:

Include=addresses, [email protected], searchfor=fl

Given the following URI request from the consumer:

http://api.com/v1/People/Search?searchfor=fl&[email protected]&include=addresses

The resulting signature base should order the parameters as:

[email protected], include=addresses, searchfor=fl

Note the case difference in the querystring parameter "include". From what I understand, lexicographical byte value ordering will order parameters using the ascii value and then order asc.

Since I = 73 and i = 105, the capital I should be ordered before the lowercase i.

I have the following so far:

IEnumerable<QueryParameter> queryParameters = parameters
.OrderBy(parm => parm.Key)
.ThenBy(parm => parm.Value)
.Select(
parm => new QueryParameter(parm.Key, UrlEncode(parm.Value)));

But that will not cover the ascii character by character sort (IncLude=test&Include=test will not sort properly).

Any thoughts on how to make an efficient algorithm that will answer this problem? Or how to make the sort case sensitive via ICompare?

A: 

I solved the problem by creating a custom comparer, however, it seems clunky and I feel there must be a better way:

public class QueryParameterComparer : IComparer<QueryParameter> {
    public int Compare(QueryParameter x, QueryParameter y) {
          if(x.Key == y.Key) {
             return string.Compare(x.Value, y.Value, StringComparison.Ordinal);
          }
           else {
             return string.Compare(x.Key, y.Key, StringComparison.Ordinal);
          }
    }
}

Using the Ordinal string comparison is what did it for me. It does byte comparisons which is exactly what I needed.

Nick
A: 

Nick, as you've discovered StringComparison.Ordinal is the way to go. I just wanted to call out a caution that you sort AFTER you URI encode each of the keys and values.

BTW, there are already a few OAuth libraries out there, DotNetOpenAuth being my favorite (disclaimer: for biased reasons). Are you sure you want to build/maintain this one?

Andrew Arnott
Andrew:Thx for the response. I rolled my own Service Provider implementation for 2 reasons1. I wanted to understand the OAuth protocol for myself and for our consumers - what better way to gain understanding than by doing2. There are business cases that required extending the protocol - https://demo.staging.fellowshiponeapi.com/v1/Util/AuthDocs.help I have looked at DotNetOpenAuth, it seems like a very slick implementation - you must have busted it to get as much functionality in there as you did!
Nick
A: 

I had problem with the same expression (though it is not misspelled anymore in the OAuth documentation, - if that's the place where it was misspelled.)

Wikipedia sais, "lexicographical ordering" has meaning, when the letter ordering is given. It specifies the ordering of series of elements (letters) when the element's order is specified already.

It sounds reasonable to me. :).

Dov