I'm trying to implement authorization through Last.fm. I'm submitting my arguments as a Dictionary to make the signing easier. This is the code I'm using to sign my calls:
public static string SignCall(Dictionary<string, string> args)
{
IOrderedEnumerable<KeyValuePair<string, string>> sortedArgs = args.OrderBy(arg => arg.Key);
string signature =
sortedArgs.Select(pair => pair.Key + pair.Value).
Aggregate((first, second) => first + second);
return MD5(signature + SecretKey);
}
I've checked the output in the debugger, it's exactly how it should be, however, I'm still getting WebExceptions every time I try, meaning the API is returning "Invalid Method Signature". This means it's not accepting the signature SignCall is generating.
Here's my code I use to generate the URL in case it'll help:
public static string GetSignedURI(Dictionary<string, string> args, bool get)
{
var stringBuilder = new StringBuilder();
if (get)
stringBuilder.Append("http://ws.audioscrobbler.com/2.0/?");
foreach (var kvp in args)
stringBuilder.AppendFormat("{0}={1}&", kvp.Key, kvp.Value);
stringBuilder.Append("api_sig="+SignCall(args));
return stringBuilder.ToString();
}
And sample usage to get a SessionKey:
var args = new Dictionary<string, string>
{
{"method", "auth.getSession"},
{"api_key", ApiKey},
{"token", token}
};
string url = GetSignedURI(args, true);
EDIT:
Oh, and the code references an MD5 function implemented like this:
public static string MD5(string toHash)
{
byte[] textBytes = Encoding.UTF8.GetBytes(toHash);
var cryptHandler = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hash = cryptHandler.ComputeHash(textBytes);
return hash.Aggregate("", (current, a) => current + a.ToString("x2"));
}
Also, here's the API documentation: API - Last.fm, with this page detailing authorization.