private static string GenerateIFrameSignature(HttpRequest req, string secretKey)
{
const string c_unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
// We cannot use the HttpUtility.UrlEncode method because it produces lowercase output as OAuth requires uppercase.
// The code of the delegate was extracted out of MySpaceToolkit library.
Func UrlEncode = (value) =>
{
StringBuilder result = new StringBuilder();
foreach (char symbol in value)
{
if (c_unreservedChars.IndexOf(symbol) != -1)
{
result.Append(symbol);
}
else
{
result.Append('%' + String.Format("{0:X2}", (int)symbol));
}
}
return result.ToString();
};
var sortedKeysWOSig = req.QueryString.AllKeys.Where(k => k != "oauth_signature").OrderBy(k => k);
var query = new StringBuilder();
foreach (string key in sortedKeysWOSig)
{
if (query.Length > 0) query.Append('&');
query.Append(UrlEncode(key))
.Append('=')
.Append(UrlEncode(req.QueryString[key]));
}
StringBuilder @base = new StringBuilder();
@base.Append("GET&")
.Append(UrlEncode(req.Url.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.Unescaped)))
.Append('&')
.Append(UrlEncode(query.ToString()));
using (KeyedHashAlgorithm alg = HMACSHA1.Create())
{
//according to http://oauth.googlecode.com/svn/spec/core/1.0/oauth-core-1_0.html#rfc.section.9.2 we should concat [Consumer Secret] + & + [Token Secrect]. The latter one is not provided by MySpace. So we imply empty string in this place.
alg.Key = Encoding.ASCII.GetBytes(secretKey + "&");
byte[] dataBuffer = Encoding.ASCII.GetBytes(@base.ToString());
byte[] hashBytes = alg.ComputeHash(dataBuffer);
return Convert.ToBase64String(hashBytes);
}
}
There is no reason to use the UrlEncode as delegate except placing it in a single method for readability of this post.
After comparing signature out of 'oauth_signature' query string parameter and the one the method above returns you can also verify auth timestamp to be up to date:
private const string _oauthTimestampKey = "oauth_timestamp";
private static readonly TimeSpan _staledInterval = TimeSpan.FromMinutes(10);
private static readonly DateTime _stDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
...
long authTime;
if (!Int64.TryParse(request.QueryString[_oauthTimestampKey], NumberStyles.Any, CultureInfo.InvariantCulture, out authTime))
{
#region Logging
if (_log.IsDebugEnabled) _log.DebugFormat("Couldn't parse oauth_timestamp value {0}", authTime);
#endregion
return false;
}
var now = DateTime.UtcNow;
DateTime time = _stDate.AddSeconds(authTime);
if (now - time > _staledInterval)
{
#region Logging
if (_log.IsDebugEnabled) _log.DebugFormat("Auth time was too late. Expected greater than {0}. Actual was {1}", now - _staledInterval, time);
#endregion
return false;
}

You can't delete from a collection during looking it through by enumerator.