0

Simply trying to get an access token to Twitter API with a c# .net program. I have composed the http post request as follows (leaving out the catch statements to save space):

        HttpWebRequest request;
        request = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/oauth2/token");

        request.Method = "POST";
        request.Host = "api.twitter.com";
        request.UserAgent = "Dev Site"; 
        request.Headers.Set("Authorization", "Basic " + credentialBase64);
        request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
        //request.Headers.Set("Accept-Encoding", "gzip");

        try
        {
            WebResponse response = (HttpWebResponse)request.GetResponse();
            Stream dataStream = response.GetResponseStream();
            byte[] requestBody = ASCIIEncoding.ASCII.GetBytes(HttpUtility.UrlEncode("grant_type=client_credentials"));
            request.ContentLength = requestBody.Length;
            dataStream.Write(requestBody, 0, requestBody.Length);
            StreamReader reader = new StreamReader(dataStream);
            twitterString = reader.ReadToEnd();


        }

Twitter api is sending back the response: {"errors":[{"code":"170","message":"Missing required parameter: grant_type","label":"forbidden_missing_parameter}]}

I understand what the error means. It is telling me that I am not including the content-body grant_type=client_credentials. But as you can see I AM sending that content-body with the Stream.Write method.

At first I assumed it was because the string was not UrlEncoded, maybe it needed a backslash before the equals sign or something. So I UrlEncoded the string just to make sure. I think it must still be in the wrong format somehow but I am not sure how.

Why is the Twitter api not getting the content-body I am sending to them?

Update: I have taken the advice of @Linvi and copied exactly the format of the article at How to set the content of an HttpWebRequest in C#? . Here is my current code:

        byte[] buffer = ASCIIEncoding.ASCII.GetBytes(HttpUtility.UrlEncode("grant_type=client_credentials"));
        var webReq = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/oauth2/token");
        webReq.Method = "POST";
        webReq.Host = "api.twitter.com";
        webReq.Headers.Set("Authorization", "Basic " + credentialBase64);
        webReq.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
        webReq.ContentLength = buffer.Length;

        var reqStream = webReq.GetRequestStream();
        reqStream.Write(buffer, 0, buffer.Length);
        reqStream.Close(); 
        var webResp = (HttpWebResponse)webReq.GetResponse();

I am still getting a response of '403' in the format: {"errors":[{"code":"170","message":"Missing required parameter: grant_type","label":"forbidden_missing_parameter}]}.

I have tested this with a local program that looks at the content body, and it is coming out null. I cannot figure out why my content body isn't being written.

Community
  • 1
  • 1
jimboweb
  • 4,362
  • 3
  • 22
  • 45
  • Possible duplicate of [How to set the content of an HttpWebRequest in C#?](http://stackoverflow.com/questions/5527316/how-to-set-the-content-of-an-httpwebrequest-in-c) – Linvi Jun 14 '16 at 01:10

2 Answers2

1

It would be good if you had actually shared more information but regarding grant_type, it is required if you want to use Application Only Credentials (only using the consumer key and consumer secret).

In this case you need to add this to your HttpRequestMessage (HttpClient) :

request.Content = new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded");

For old HttpWebRequest use :

byte[] requestBytes = new ASCIIEncoding().GetBytes(inputData);
//get the request stream to write the post to
Stream requestStream = request.GetRequestStream();
//write the post to the request stream
requestStream.Write(requestBytes, 0, requestBytes.Length);

Source : How to set the content of an HttpWebRequest in C#?

Community
  • 1
  • 1
Linvi
  • 2,077
  • 1
  • 14
  • 28
  • What you listed is what I assumed would work, but HttpWebRequest does not have a Content property. If I try to include your line I get the error 'HttpWebRequest does not contain a definition for 'Content' – jimboweb Jun 02 '16 at 19:55
  • This is the case with the `Microsoft.Net.HttpClient`. I don't have time right now to give you the `HttpWebRequest` version of the solution but I will. – Linvi Jun 02 '16 at 22:37
  • To set the content of `HttpWebRequest` look here http://stackoverflow.com/questions/5527316/how-to-set-the-content-of-an-httpwebrequest-in-c – Linvi Jun 03 '16 at 10:48
  • Any comment as to why you someone put a -1 there? – Linvi Jun 13 '16 at 15:40
  • When you first gave me the answer it used a property that doesn't exist for HttpWebRequest. I see now you were using the comment for HttpClient instead, which is fine but I can't change it. Make some edit to the answer and I can take off the -1 vote. – jimboweb Jun 13 '16 at 19:10
  • And have you read the comment just above? This is the case with the Microsoft.Net.HttpClient. I don't have time right now to give you the HttpWebRequest version of the solution but I will. Such a shame to try to help such persons. More importantly when I gave you the exact solution you used in the comment above... – Linvi Jun 14 '16 at 01:05
  • Yes. I voted before I saw the comment. I voted down because the answer didn't answer the question and I already knew that the problem was that the request didn't have content, I just didn't know how to do it. As I said, make ANY EDIT AT ALL to the post and I'll be able to get rid of the down vote. But if you just want to give me more angry comments there is literally nothing I can do. – jimboweb Jun 15 '16 at 15:05
  • I am not angry, I just think you should treat people trying to help you differently. I did not throw an answer to you and left you with it. When you raised the fact that you wanted it to work for HttpWebRequest I tried to guide you to the correct answer. Anyway, now it is updated. – Linvi Jun 15 '16 at 16:10
-2

Finally got it to work. I had to stop urlencoding the grant type request. For anyone else trying to get the access token from Twitter api, here is the code that works:

        byte[] buffer = ASCIIEncoding.ASCII.GetBytes("grant_type=client_credentials");
        var webReq = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/oauth2/token");

        webReq.Method = "POST";
        webReq.Host = "api.twitter.com";
        webReq.Headers.Set("Authorization", "Basic " + credentialBase64);
        webReq.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
        webReq.ContentLength = buffer.Length;

        var reqStream = webReq.GetRequestStream();
        reqStream.Write(buffer, 0, buffer.Length);
        reqStream.Close();
        var webResp = (HttpWebResponse)webReq.GetResponse();
jimboweb
  • 4,362
  • 3
  • 22
  • 45