I have a Windows 8 and a Windows Phone 8 app that serves as a social media dashboard and it get's tweets using the twitter search api. This was originally implemented using the Twitter API 1 and worked with no authentication so since it didn't need any additional 3rd party libs it was placed in the PCL part of the solution. For the same reason I wanted the update to using 1.1 API to be done without any libs. I have found various samples online on the Twitter dev community and on codeproject and modified them to work with the PCL.
Here is the part of the code attempting to search twitter:
private static async Task<string> doTheTwitterMagic(string query)
{
var oauth_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var oauth_token_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var oauth_consumer_key = "XXXXXXXXXXXXXXXXX";
var oauth_consumer_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var resource_url = "https://api.twitter.com/1.1/search/tweets.json";
// oauth implementation details
var oauth_version = "1.0";
var oauth_signature_method = "HMAC-SHA1";
Encoding ascii = new AsciiEncoding();
// unique request details
var oauth_nonce = Convert.ToBase64String(
ascii.GetBytes(DateTime.Now.Ticks.ToString()));
var timeSpan = DateTime.UtcNow
- new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
// create oauth signature
var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
"&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&q={6}";
var baseString = string.Format(baseFormat,
oauth_consumer_key,
oauth_nonce,
oauth_signature_method,
oauth_timestamp,
oauth_token,
oauth_version,
Uri.EscapeDataString(query)
);
baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));
var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
"&", Uri.EscapeDataString(oauth_token_secret));
string oauth_signature;
using (HMACSHA1 hasher = new HMACSHA1(ascii.GetBytes(compositeKey)))
{
oauth_signature = Convert.ToBase64String(
hasher.ComputeHash(ascii.GetBytes(baseString)));
}
// create the request header
var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
"oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
"oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
"oauth_version=\"{6}\"";
var authHeader = string.Format(headerFormat,
Uri.EscapeDataString(oauth_nonce),
Uri.EscapeDataString(oauth_signature_method),
Uri.EscapeDataString(oauth_timestamp),
Uri.EscapeDataString(oauth_consumer_key),
Uri.EscapeDataString(oauth_token),
Uri.EscapeDataString(oauth_signature),
Uri.EscapeDataString(oauth_version)
);
return authHeader;
}
public static async Task<List<TwitterObject>> GetTweetsFromSearchAsync(string query)
{
try
{
string authHeader = await doTheTwitterMagic(query);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/1.1/search/tweets.json?q="+query);
webRequest.Headers[HttpRequestHeader.Authorization] = authHeader;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "GET";
var webResponse = await webRequest.GetResponseAsync();
var json = string.Empty;
using (var reader = new StreamReader(webResponse.GetResponseStream()))
json = await reader.ReadToEndAsync();
var jsonObject = JObject.Parse(json);
var results = new List<TwitterObject>();
foreach (JToken token in jsonObject["results"])
results.Add(token.ToObject<TwitterObject>());
return results;
}
catch (Exception e) { throw e; }
}
N.B.:The AsciiEncoding is a custom implementation of ASCIIEncoding since it's not available in the PCL at the moment.
Now I attempted the standard debugging and the first thing I looked at was the Twitter OAuth tool and here are the results of OAuth tools vs my app
OAuth Tool Signature base string:
GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fsearch%2Ftweets.json&oauth_consumer_key
%3DywWuYGASkHMsHsC22Vpw%26oauth_nonce%3D3c30afb0c2a391d3b4e4ba3da057c2ca%26oauth_
signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1371309728%26oauth_token%3D16702
294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM%26oauth_version%3D1.0%26q%3Dcsmcr
My app Signature base string:
GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fsearch%2Ftweets.json&oauth_consumer_key
%3DywWuYGASkHMsHsC22Vpw%26oauth_nonce%3DNjM1MDY5MTA1MzA2MTU1NTgz%26oauth_signatur
e_method%3DHMAC-SHA1%26oauth_timestamp%3D1371310131%26oauth_token%3D16702294-3WNj
fZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM%26oauth_version%3D1.0%26q%3D%2540csmcr
And at the first look the only difference being the nonce but that shouldn't be an issue
Edit note: I have just noticed that there is a small difference in the above at the end of the both where in the OAuth Tool one I have %26q%3Dcsmcr and my app generates %26q%3D%2540csmcr but that's just since I forgot to include a character in the query in the OAuth tool. After adding the character the string became the same at the end.
OAuth Tool Authorization header:
Authorization: OAuth oauth_consumer_key="ywWuYGASkHMsHsC22Vpw",
oauth_nonce="3c30afb0c2a391d3b4e4ba3da057c2ca",
oauth_signature="tofmGp6qaAUAPZnQHhQlVFWN40M%3D",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1371309728",
oauth_token="16702294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM",
oauth_version="1.0"
My app Authorization header:
Authorization: OAuth oauth_nonce="NjM1MDY5MDk5NTY5Nzc1MTc5",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1371309557",
oauth_consumer_key="ywWuYGASkHMsHsC22Vpw",
oauth_token="16702294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM",
oauth_signature="q1544JDPUXdUwY3fmEk3mtGGEwk%3D", oauth_version="1.0"
Again not much difference other than the nonce and the signature. The order of the key-value pairs seems to make no difference as I tested with rearranging them and still had the same problem.
So the problem that I have is that when the function runs I always get the 401 Unauthorized error with the
{"errors":[{"message":"Could not authenticate you","code":32}]}
error.
Any pointers would be very much appreciated.
Edit: Did some more testing with this, took the nonce and the timestamp generated by the Twitter OAuth tool and just hardcoded them in my app to check if the signature was fine and it turned out it was, I was getting the same oauth_signature as the one in the OAuth tool. That would mean that the Auth header should also be totally fine. So I guess the problem is somewhere in my request.
(Answered by the OP in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
Problem solved by replacing the httpwebrequest implementation with the httpclient. The issue was that the Expect:100-Continue header was being added, and twitter doesn't support this. Due to limitations in PCL it wasn't possible to disable this in httpwebrequest replacing it all with a httpclient was a way to go. Hope this helps anyone who experiences the same issue.
Related
I am writing an API which needs to verify the OAuth token and token secrets which are created by the Twitter SDK on mobile devices.
To do this I am attempting to call account/verify_credentials.json of the Twitter API. I have jumped through all the OAuth signature generation hoops yet on every request I get the same response:
{
"errors": [{
"code": 215,
"message": "Bad Authentication data."
}]
}
I am at a loss to explain why this is occurring since I have followed Twitter's guidelines and also referenced several other questions with similar goals, yet still without luck.
Also, please note that I do not want to use a library for this. All I need to make is this one single request, so an additional library would be needless bloat. Below is my code which is generating the error response:
var httpMethod = HttpMethod.Get;
var uri = new Uri("https://api.twitter.com/1.1/account/verify_credentials.json");
var nonce = Guid.NewGuid().ToString();
var timestamp = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString(CultureInfo.InvariantCulture);
var oauthParameters = new SortedDictionary<string, string>
{
{"oauth_consumer_key", Settings.OAuth.Twitter.ConsumerKey},
{"oauth_nonce", nonce},
{"oauth_signature_method", "HMAC-SHA1"},
{"oauth_timestamp", timestamp},
{"oauth_token", accessToken},
{"oauth_version", "1.0"}
};
var signingParameters = new SortedDictionary<string, string>(oauthParameters);
var parsedQuery = HttpUtility.ParseQueryString(uri.Query);
foreach (var k in parsedQuery.AllKeys)
signingParameters.Add(k, parsedQuery[k]);
var parameterString = string.Join("&", signingParameters.Keys.Select(k => $"{Uri.EscapeDataString(k)}={Uri.EscapeDataString(signingParameters[k])}"));
var stringToSign = string.Join("&", new[] { httpMethod.Method.ToUpper(), uri.AbsoluteUri, parameterString }.Select(Uri.EscapeDataString));
var signingKey = Settings.OAuth.Twitter.ConsumerSecret + "&" + tokenSecret;
var signature = Convert.ToBase64String(new HMACSHA1(Encoding.ASCII.GetBytes(signingKey)).ComputeHash(Encoding.ASCII.GetBytes(stringToSign)));
oauthParameters.Add("oauth_signature", signature);
var authHeader = string.Join(",", oauthParameters.Keys.Select(k => $"{Uri.EscapeDataString(k)}=\"{Uri.EscapeDataString(oauthParameters[k])}\""));
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", authHeader);
var response = await client.GetAsync(uri);
return await response.Content.ReadAsStringAsync(); // always error 215
I just tried your code verbatim and it worked like a charm.
Your issue must be your twitter application keys. Try copying them in from apps.twitter.com again. If that still does not work, you may need to recreate your keys.
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);
}
Simply put, I'm trying to create a webpage with Visual Studio 2012 wherein the user will log into a page, which, when authorized, will post a tweet, and enable them to use the rest of the features on the page. I'd like to remember said users credentials to also limit the rate at which they use a certain feature.
The problem is, I have been searching for days and I am unable to find an UP TO DATE and working example for me to follow. Everything seems to be outdated. (Twitterizer ; TweetSharp) I've switched from Java to C# & .NET and still no progress.
I am now seeking direct help.. Code snippets .. Tutorials .. Anything .. So that I can accomplish this task. I'm new to .NET but used to Java & C/C++ so I don't expect to be confused by too trivial of code..
My exact request is to be able to log in with twitter, save credentials (or the user's access token, whatever) & post a tweet.
This is a basic example of how to authenticate and retrieve a user's timeline:
// You need to set your own keys and screen name
var oAuthConsumerKey = "superSecretKey";
var oAuthConsumerSecret = "superSecretSecret";
var oAuthUrl = "https://api.twitter.com/oauth2/token";
var screenname = "aScreenName";
// Do the Authenticate
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey) + ":" +
Uri.EscapeDataString((oAuthConsumerSecret)))
));
var postBody = "grant_type=client_credentials";
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
authRequest.Headers.Add("Authorization", authHeader);
authRequest.Method = "POST";
authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream stream = authRequest.GetRequestStream())
{
byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
stream.Write(content, 0, content.Length);
}
authRequest.Headers.Add("Accept-Encoding", "gzip");
WebResponse authResponse = authRequest.GetResponse();
// deserialize into an object
TwitAuthenticateResponse twitAuthResponse;
using (authResponse)
{
using (var reader = new StreamReader(authResponse.GetResponseStream())) {
JavaScriptSerializer js = new JavaScriptSerializer();
var objectText = reader.ReadToEnd();
twitAuthResponse = JsonConvert.DeserializeObject<TwitAuthenticateResponse>(objectText);
}
}
// Do the timeline
var timelineFormat = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={0}&include_rts=1&exclude_replies=1&count=5";
var timelineUrl = string.Format(timelineFormat, screenname);
HttpWebRequest timeLineRequest = (HttpWebRequest)WebRequest.Create(timelineUrl);
var timelineHeaderFormat = "{0} {1}";
timeLineRequest.Headers.Add("Authorization", string.Format(timelineHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token));
timeLineRequest.Method = "Get";
WebResponse timeLineResponse = timeLineRequest.GetResponse();
var timeLineJson = string.Empty;
using (timeLineResponse)
{
using (var reader = new StreamReader(timeLineResponse.GetResponseStream()))
{
timeLineJson = reader.ReadToEnd();
}
}
public class TwitAuthenticateResponse {
public string token_type { get; set; }
public string access_token { get; set; }
}
Please see here (The github project has asp.net and asp.net mvc examples):
Authenticate and request a user's timeline with Twitter API 1.1 oAuth
I created an an open source project for it but unfortunately it doesn't yet include the ability to send tweets. I don't think it would be difficult but I am short on time at the moment.
If I was to implement it I would find out exactly what needs to be posted by the api, as detailed here:
https://dev.twitter.com/docs/api/1.1/post/statuses/update
For the assisting of other persons who have fallen into the same gap I did... Check out this site
It will help with authenticating & signing in & retrieving basic information.
I have written some simple code for using my Twitter developer key and secret to read tweets from a public timeline. This is so I can display a user's latest tweets in their own website. The code is below.
I now wish to do something similar with their blog on Google's Blogger. I had assumed there would be a way to use my Google API key and secret to read the public content of a blog without the user needing to authenticate. I only need blog titles and dates so I can link through to the Blogger site. But I've spent 24 hours scouring the internet and cannot find any examples for getting an access token using just the key and secret.
Using the Google API SDK I have got as far as the code below but can't find a way to get the access token without getting the user to authenticate. Any advice appreciated - feel I'm banging my head against a wall! Happy to take any approach - I just want to get some Blogger content on a website I'm building...
Authenticate with Twitter:
var oAuthConsumerKey = _key;
var oAuthConsumerSecret = _secret;
var oAuthUrl = "https://api.twitter.com/oauth2/token";
// Do the Authenticate
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey) + ":" +
Uri.EscapeDataString((oAuthConsumerSecret)))
));
var postBody = "grant_type=client_credentials";
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
authRequest.Headers.Add("Authorization", authHeader);
authRequest.Method = "POST";
authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
authRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream stream = authRequest.GetRequestStream())
{
byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
stream.Write(content, 0, content.Length);
}
authRequest.Headers.Add("Accept-Encoding", "gzip");
WebResponse authResponse = authRequest.GetResponse();
// deserialize into an object
string objectText;
using (authResponse)
{
using (var reader = new StreamReader(authResponse.GetResponseStream()))
{
objectText = reader.ReadToEnd();
}
}
// objectText is JSON and contains access_token
Authenticate with Blogger??
private bloggerTest()
{
// Register the authenticator.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description)
{
ClientIdentifier = _key,
ClientSecret = _secret
};
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the service.
var service = new BloggerService(new BaseClientService.Initializer()
{
Authenticator = auth
});
var result = service.Posts.List(_blogID).Fetch();
}
private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
var state = new AuthorizationState(new[] { BloggerService.Scopes.BloggerReadonly.GetStringValue() });
// I am stuck here!
}
For accessing a public feed it is way simpler than what you are doing. There are a bunch of classes built into the .Net framework for processing RSS feeds, you can start with SyndicationFeed. To get the feed items (blog posts) is quite simple:
XDocument feed = XDocument.Load(rssUrl); //rssUrl is the URL to the rss page that (most) blogs publish
SyndicationFeed sf = SyndicationFeed.Load(feed.CreateReader());
foreach (SyndicationItem si in sf.Items)
{
..you've now got your feed item...
}
Note that this will give you the feed items but it won't give you the full web page that they appear in. (although you will get a URL for that).
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);