0
votes

resp = (HttpWebResponse)request.GetResponse();Right I know this is probably some stupid mistake or just me not being well versed in Oauth stuff but I have come to a grinding halt and have no idea where to go from here, after many searches and attempts I humbly ask for some help.

I am attempting to get a request token from Twitter to try and get a users twitter feeds, I cannot use a library for other business reasons...

Here is the code so far:

     Dictionary<string, string> parameters = new Dictionary<string, string>();
        parameters.Add("oauth_callback", "www.url.com/redirect.aspx");
        parameters.Add("oauth_consumer_key", <Consumer_KEY>);
        parameters.Add("oauth_nonce", generateNonce());
        parameters.Add("oauth_signature_method", "HMAC-SHA1");
        parameters.Add("oauth_timestamp", CurrentUNIXTimestamp.Get());
        parameters.Add("oauth_version", "1.0");

        parameters = parameters.OrderBy(x => x.Key).ToDictionary(v => v.Key, v => v.Value);
        string concat = "";
        string OAuthHeader = "OAuth ";
        foreach (string k in parameters.Keys)
        {
            if (k == "oauth_callback")
            {
                concat += k + "%3D" + EncodeToUpper(parameters[k]) + "%26";
                OAuthHeader += k + "=" + "\"" + EncodeToUpper(parameters[k]) + "\", ";
            }
            else
            {
                concat += k + "%3D" + parameters[k] + "%26";
                OAuthHeader += k + "=" + "\"" + parameters[k] + "\", ";
            }

        }

        concat = concat.Remove(concat.Length - 3, 3);

        concat = "POST&" + EncodeToUpper("https://api.twitter.com/oauth/request_token" ) + "&" + concat;

        //byte[] content = Encoding.UTF8.GetBytes(concat);

        HMACSHA1 hmacsha1 = new HMACSHA1();
        hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", EncodeToUpper(<CONSUMER SECRET>, ""));

        byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(concat);
        byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);

        string hash =  Convert.ToBase64String(hashBytes);
        OAuthHeader += "oauth_signature=\"" + EncodeToUpper(hash) + "\"";

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/oauth/request_token");
        request.Method = "POST";
        request.Headers["Authorization"] = OAuthHeader;

        StringBuilder responding = new StringBuilder();
        HttpWebResponse resp = null;
        try
        {
            resp = (HttpWebResponse)request.GetResponse();
        }
        catch (WebException exc)
        {
            lblError.Text = "Error Connecting to Social Network " + exc.Message;
        }
        if (resp != null)
        {
            using (StreamReader reader = new StreamReader(resp.GetResponseStream()))
            {
                responding.Append(reader.ReadToEnd());
            }
        }

An Example of the Nonce is "ne8ehvVr0pW2EUxNHdxdyqbi8Fwphatt3SW1yerTyXH" and the CurrentUNIXTimestamp is generated by

         public static class CurrentUNIXTimestamp
         {
              public static string Get()
              {
                    return Convert.ToString((int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
               }
         }

I have tried as many things as I can think of, there is no longer a client/browser issue (which was many other answers), the server time is correct to British Summer Time (I don't know whether that would be an issue but I tried adding an hour to the unix time stamp still a 401.), and i have defined the callback url on the twitter app page

I have got the same app working with facebook (I know its different oauth but may help)

The actual error comes at resp = (HttpWebResponse)request.GetResponse();, which comes up with a 401 error. I couldn't get any further details from the exc.response object, could anyone say how to get something useful out of the error in VS2008?

Thanks for any answers

1

1 Answers

0
votes

The hardest problem I had implementing OAuth was dealing with character encoding. It's very particular.

Here is the code I ended up writing for it.

private static string UrlEncode(IEnumerable<KeyValuePair<string, object>> parameters)
{
    StringBuilder parameterString = new StringBuilder();

    var paramsSorted = from p in parameters
                       orderby p.Key, p.Value
                       select p;

    foreach (var item in paramsSorted)
    {
        if (parameterString.Length > 0)
        {
            parameterString.Append("&");
        }

        if(item.Value.GetType() == typeof(string) )
                parameterString.Append(
                        string.Format(
                                CultureInfo.InvariantCulture,
                                "{0}={1}",
                                UrlEncode(item.Key),
                                UrlEncode(item.Value as string)));
    }

    return UrlEncode(parameterString.ToString());
}

public static string UrlEncode(string value)
{
    if (string.IsNullOrEmpty(value))
    {
        return string.Empty;
    }

    value = Uri.EscapeDataString(value);

    // UrlEncode escapes with lowercase characters (e.g. %2f) but oAuth needs %2F
    value = Regex.Replace(value, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());

    // these characters are not escaped by UrlEncode() but needed to be escaped
    value = value
        .Replace("(", "%28")
        .Replace(")", "%29")
        .Replace("$", "%24")
        .Replace("!", "%21")
        .Replace("*", "%2A")
        .Replace("'", "%27");

    // these characters are escaped by UrlEncode() but will fail if unescaped!
    value = value.Replace("%7E", "~");

    return value;
}

If you really get fed up, you can use the WebRequestBuilder class from my library to do all the OAuth stuff for you: http://www.twitterizer.net/