Getting Error 400: Bad request at authenticate via Twitch.tv api - c#

I am new here and I hope someone can help me. I try to connect to twitch.tv I am trying to get an oauth2 authentication on twitch.tv with a small C# program. I am using the twitch.tv authentication request. Here is my C# code:
var loginURL = "https://api.twitch.tv/kraken/oauth2/authorize?
response_type=code&"+
client_id="+ clientID+"
"&redirect_uri=http://localhost&"+
"state=TWStreamingStateAuthenticated";
this.richTextBox1.Text = loginURL;
string code = get_DownLoadString(loginURL);
this.richTextBox1.Text = code;
This is the part, which does not work. It gives me the Error 400: Bad Request.
WebRequest request = WebRequest.Create("https://api.twitch.tv/kraken/oauth2/token");
request.Method = "POST";
string postData = "client_id=" + clientID +
"&client_secret=" + clientSecret +
"&grant_type=authorization_code" +
"&redirect_uri=http://localhost" +
"&code=" + code +
"&state=TWStreamingStateAuthenticated";
ASCIIEncoding encoding = new ASCIIEncoding();
postData = HttpUtility.UrlEncode(postData);
byte[] byteArray = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream datatream = request.GetRequestStream();
datatream.Write(byteArray, 0, byteArray.Length);
datatream.Close();
WebResponse respone = request.GetResponse();
MessageBox.Show(((HttpWebResponse)respone).StatusDescription);
I hope someone can help me.
And here is the Get_DownloadString(string URL) Method.
private static string get_DownLoadString(string URL)
{
try
{
string temp = (new WebClient().DownloadString(URL));
return temp;
}
catch (WebException)
{
return null;
}
}

This code doesn't look right to me:
string postData = "client_id=" + clientID +
"&client_secret=" + clientSecret +
"&grant_type=authorization_code" +
"&redirect_uri=http://localhost" +
"&code=" + code +
"&state=TWStreamingStateAuthenticated";
ASCIIEncoding encoding = new ASCIIEncoding();
postData = HttpUtility.UrlEncode(postData);
byte[] byteArray = encoding.GetBytes(postData);
// ...
You are URL-encoding the entire post-data string. This has the effect of converting the & and = signs in the post data to %26 and %3d respectively. When the remote server receives this data, it will scan through it looking for the & and = signs in order to separate out the parameter names and values. Of course, it won't find any, so it will assume you have one big parameter name with no value. The server is probably expecting values for each of the six parameters you are attempting to send, but seeing values for none of them, and this may be why you are getting a 400 Bad Request error.
Instead of URL-encoding the whole string, URL-encode parameter values that may contain characters other than letters and numbers. I would try the following instead:
string postData = "client_id=" + HttpUtility.UrlEncode(clientID) +
"&client_secret=" + HttpUtility.UrlEncode(clientSecret) +
"&grant_type=authorization_code" +
"&redirect_uri=" + HttpUtility.UrlEncode("http://localhost") +
"&code=" + HttpUtility.UrlEncode(code) +
"&state=TWStreamingStateAuthenticated";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byteArray = encoding.GetBytes(postData);
// ...
This way, the remote server will still see the & and = characters, and so will be able to pull out the parameter names and values. Because we've URL-encoded the client ID, client secret, URL and code, any characters they contain that may have meaning in a URL will not have that meaning and will be received by the remote server as intended.
Also, if you are still getting a 400 Bad Request error response, try reading the contents of the response stream, obtained by calling GetResponseStream() on the response. Often that will contain a message that will help you figure out what's gone wrong.
Having had a closer look at your code, it seems you have a misunderstanding about how OAuth authentication works. Your getDownload_String method will not get the access code you want, it will only get the HTML text of a Twitch login page.
This is how OAuth authentication works:
Your app sends the user to a login URL, to allow the user to log in to Twitch.
In the web browser, the user then enters their login credentials and submits the page to Twitch.
The Twitch API then responds by redirecting the user's web browser to the redirect URL, with a code appended. Your web app then reads this code out of the URL.
If your code is in a web app it will be able to respond to the URL redirected to in step 3. Alternatively, you may be able to use a WebBrowser control (Windows Forms, WPF) to handle the Twitch login, and handle a Navigating event. If the URL being navigated to begins with the redirect URL, grab the code out of the URL, cancel the navigation and hide the login web-browser control.
The presence of what appears to be a RichTextBox control, along with your comment about your code being a 'small C# application', makes me think that your code is a Windows Forms or WPF application. If this is the case, then you will need to either:
use a WebBrowser control as I described above,
replace your WinForms/WPF app with a web app, or
get in contact with Twitch to request the use of the password flow (which appears not to require a redirect), and use that instead.

Related

Web Service Authorization header returning odd characters in service

I have written a WPF application that sends a POST WebHTTPRequest to a WCF service. The service required windows credentials to perform operations on the server. When the service receives the HTTP request, it is unable to parse the Authorization header.
The POST request begins like this.
HttpWebRequest req = WebRequest.CreateHttp(url);
req.ContentType = "application/json;charset=UTF-8";
req.Accept = "application/json";
req.Headers.Add("Authorization", Base64Encode(Details.username + ":" + Details.password + ":" + Details.domain));
req.Method = "POST";
byte[] reqBytes = Encoding.ASCII.GetBytes(body.ToString());
And is received on the service like this
IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
WebHeaderCollection headers = request.Headers;
if (headers["Authorization"] != null)
{
cred = headers["Authorization"];
} else
{
HttpContext.Current.Response.Write(result);
return;
}
I print the "cred" variable to a log file and what I get begins something like this "敎潧楴瑡⁥䥙䝉䅺䝙" which, quite clearly, is wrong. Can anybody tell me why I'm getting this output as opposed to the input consisting of the English characters I sent the request with?
The problem is that you encoded a UTF-8 encoded string into Base64.
You specified that the charset type for your JSON file is UTF-8 here:
req.ContentType = "application/json;charset=UTF-8";
So when you tried to encode your Authentication into Base64 it would have ruined your string.
req.Headers.Add("Authorization", Base64Encode(Details.username + ":" + Details.password + ":" + Details.domain));
Try a different way of encoding the string

Use Webbrowser control to get and post data?

I have a windows form with a webbrowser control. Using this control, I need login to a website, and get and post data.
The login part will remain manually because various headers and cookies and created and stored.
However, is it possible to use the control to send post/get requests?
I do something like this and it works for me.
string postData = "value1=" + 1 + "&value2=" + 2 + "&value3=" + 3;
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
byte[] bytes = encoding.GetBytes(postData);
string url = "http://www.domain.com/addSomething";
webBrowser1.Navigate(url, string.Empty, bytes, "Content-Type: application/x-www-form-urlencoded");
I hope it is of help.

In C#, what is the right way to post attachments to Confluence REST API?

I am migrating from Confluence's SOAP API to using their REST API. I see there is support for adding attachments to a page (by doing a POST) but I am running into issues getting it to work (I am getting a 403: Forbidden Error message). I have other "get" items working fine through the rest api but doing an attachment post seems to keep failing.
Here is my current code (given a specific filename):
byte[] rawData = File.ReadAllBytes(filename);
var pageId = "11134";
var url = new Uri("http://example.com:9088/rest/api/content/" + pageId + "/child/attachment");
var requestContent = new MultipartFormDataContent();
var imageContent = new ByteArrayContent(rawData);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse(attachement.contentType);
requestContent.Add(imageContent, "file", attachement.fileName);
requestContent.Headers.Add("X-Atlassian-Token", "nocheck");
Can you see if I am doing anything wrong above?
403 status indicates that request is not authorized. In order to authorize a request you need to specify Authorization header. Confluence REST API supports Basic authorization scheme. For basic authentication you need to specify the following header with each request: Authorization: Basic username:password where username:password part should be Base64-encoded. You can use the following code in order to do this:
string userName;
string password;
string authorizationString = userName + ":" + password;
string encodedValue = Convert.ToBase64String(Encoding.ASCII.GetBytes(authorizationString));
string authorizationHeaderValue = "Basic " + encodedValue;
requestContent.Headers.Add("Authorization", authorizationHeaderValue);
According to this link you also should specify the following url parameter with each request: os_authType=basic.
HTTP basic authentication: (Authorization HTTP header) containing
'Basic username:password'. Please note however, username:password must
be base64 encoded. The URL must also contain the 'os_authType=basic'
query parameter.
Note: make sure to connect via https if using basic authentication;
From Confluence documentation (RTFM)
In order to protect against XSRF attacks, because this method accepts multipart/form-data, it has XSRF protection on it. This means you must submit a header of X-Atlassian-Token: nocheck with the request, otherwise it will be blocked.
Add this before the Post
httpClient.Headers.Add("X-Atlassian-Token", "nocheck");
Here is the way I prefer:
string url = "https://localhost:8080/confluence/rest/api/content/123456/child/attachment";
string filename = #"C:\temp\test.txt";
using (var client = new WebClient())
{
string authorizationString = username + ":" + password;
string encodedValue = Convert.ToBase64String(Encoding.ASCII.GetBytes(authorizationString));
client.Headers.Add("Authorization", "Basic " + encodedValue);
client.Headers.Add("X-Atlassian-Token", "nocheck");
byte[] result = client.UploadFile(url, filename);
string responseAsString = Encoding.Default.GetString(result);
}

How to handle Invitation API of Linkedin in c# Asp.NET

Can any one guide me how to tackle with Linkedin Invitation API in c# asp.net. I want to send invitation to particular user from my app via this api, but don't find any sufficient information to start it. Can any one give me some example to start with. I have already get list of users from linkedin search api. Now i want to send invitation to those users.
Thanks in advanced. Hope best answer will come out.
Thanks
Finally, it's done. I have successfully implement linkedin invitation api with asp.net c#.
I am posting sample code here, for other users who want to implement it.
try
{
string uid=uniqueid of user,to whom you want to send request.
// if you get this user bysearch api or 1st connection, then from http-header response, you will find value field. split this value by ':' and store in two variable
string name=splitvalue1;
string namevalue=splitvalue2;
string xml = "<?xml version='1.0' encoding='UTF-8'?><mailbox-item><recipients><recipient><person path=\"/people/id=" + uid + "\" /></recipient></recipients>";
xml += "<subject>Invitation to Connect</subject>";
xml += "<body>Please join my professional network on LinkedIn.</body>";
xml += "<item-content><invitation-request><connect-type>friend</connect-type><authorization><name>" + name + "</name><value>" + namevalue + "</value></authorization></invitation-request></item-content></mailbox-item>";
string accessCodeUri = "https://api.linkedin.com/v1/people/~/mailbox?oauth2_access_token=" + Session["accessCode"]; // this is session value which you get on authorization success return by linkedin
WebRequest request = WebRequest.Create(accessCodeUri);
request.Method = "POST";
request.ContentType = "application/xml";
request.ContentLength = xml.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(xml);
requestWriter.Close();
WebResponse webResponse = request.GetResponse();
//success
}
catch(WebException exc)
{
}
Hope it helps other.

obtaining oauth_verifier from callback

I have searched high and low for an answer to this problem. Basically, I am creating a C# application which (In it's first incarnation) will authenticate with the Projectplace API which uses OAuth 1.0a. It currently returns the oauth_verifier to the address bar, but when I use the var response = request.GetResponse(); method, it returns the oauth_token and oauth token_secret which I sent as part of the authorization in the first place.
Perhaps I am misunderstanding the way this process is supposed to work, but I've read every single answer out there and none seem to address this question. Do you have to, or is it possible, to pull the verifier code from the address bar (or wherever else it can be obtained), after I have entered my username and password on the authentication page after callback URL is loaded?
I believe OAuth1.0a requires the verification code to retrieve an access token, and I cannot find a simple way to pull the verification code.
I would really appreciate any help, it's driving me nuts!!
UPDATED 03.12.12
Thanks for your response!
Essentially, I am the client attempting to retrieve the oauth_verifier from the oauth provider after sending this initial request below, my next step is to authorize then retrieve verifier. I tried the following, hopefully as you suggested, like swimming in the deep end here :)
//Generate string for initiation request.
requestUri.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
requestUri.AppendFormat("oauth_nonce={0}&", nonce);
requestUri.AppendFormat("oauth_timestamp={0}&", timeStamp);
requestUri.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
requestUri.AppendFormat("oauth_version={0}&", "1.0");
requestUri.AppendFormat("oauth_signature={0}", signature);
var request = (HttpWebRequest)WebRequest.Create(new Uri(requestUri.ToString()));
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var tokenSecret = parts[0].Substring(parts[0].IndexOf('=') + 1);
var queryString2 = String.Format("oauth_token={0}", token);
//AUTHORIZE WITH CREDENTIALS FROM USER.
var authorizeUrl = "https://api.projectplace.com/authorize?" + queryString;
Process.Start(authorizeUrl);`
//TRY AND READ VERIFICATION STRING AFTER AUTHORIZATION REDIRECT`
String oauthVerifier = HttpContext.Current.Request.QueryString["oauth_verifier"];
Unfortunately, once i've done this, I can't seem to get a querystring returned showing the oauth_verifier that I am clearly seeing in the string showing in the address bar. (Yes it's a very newbish way of describing it, i'm learning the code as well as OAuth :P).
Thanks for your help so far. I tried to run the above, but it just said that says "Object reference not set to an instance of an object.".
Also, if I attempt to use the previous code I used to obtain the querystring / response? from the initiation request using the following lines, the querystring3 just comes back as blank... really frustrating! :)
var queryString3 = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts3 = queryString3.Split('&');
I'm going to assume that by "in the address bar" you mean that the oauth_verifier is passed to your site from the ProjectPlace server via a query string parameter in the redirect URL. In order to read this in your C# server side code, you would use something like the following (I modified your sample code for this solution):
requestUri.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
requestUri.AppendFormat("oauth_nonce={0}&", nonce);
requestUri.AppendFormat("oauth_timestamp={0}&", timeStamp);
requestUri.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
requestUri.AppendFormat("oauth_version={0}&", "1.0");
requestUri.AppendFormat("oauth_signature={0}", signature);
var request = (HttpWebRequest)WebRequest.Create(new Uri(requestUri.ToString()));
//Note: this is unnecessary - GET is the default
request.Method = WebRequestMethods.Http.Get;
//By casting to HttpWebResponse you get access to the QueryString property
var response = request.GetResponse() as HttpWebResponse;
var oauthVerifier = response.QueryString["oauth_verifier"];
//The response stream contains the HTTP response body,
//which will not contain the URL to which the redirect is sent
//I'm not sure if there is anything there that you will need
var responseBody = new StreamReader(response.GetResponseStream()).ReadToEnd();
//AUTHORIZE WITH CREDENTIALS FROM USER. -- Not sure what this section is doing
var queryString = string.Format("oauth_token={0}", oauthVerifier);
var authorizeUrl = "https://api.projectplace.com/authorize?" + queryString;
Process.Start(authorizeUrl);

Categories

Resources