/* * (Copyright (c) 2011, Shannon Whitley http://voiceoftech.com/ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of conditions * and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions * and the following disclaimer in the documentation and/or other materials provided with the distribution. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Net; using System.IO; using System.Text; using System.Collections.Generic; using System.Xml; using TradeIdeas.XML; using System.Collections.Specialized; namespace TradeIdeas.TIProGUI { public class oAuthTwitter : OAuthBase { //When the TI Pro is actually *installed*(not using VS on another machine //the app.config file doesn't get read initially, which leads to a consumer //key null exception. Due to security issues, the consumer/key secrets are //hardcoded here in this program... public enum Method { GET, POST }; public const string REQUEST_TOKEN = "https://api.x.com/oauth/request_token"; public const string AUTHORIZE = "https://api.x.com/oauth/authorize"; public const string ACCESS_TOKEN = "https://api.x.com/oauth/access_token"; public Exception LastException = null; private string _consumerKey = ""; private string _consumerSecret = ""; private string _token = ""; private string _tokenSecret = ""; #region Properties public string ConsumerKey { get { if (_consumerKey.Length == 0) { _consumerKey = GuiEnvironment.TwitterAPIKey; //"LaaOgjijU1MuFO3ROBORifnea"; _phrases.Node("CONSUMER_KEY").PropertyForCulture("TEXT", "***"); } return _consumerKey; } set { _consumerKey = value; } } public string ConsumerSecret { get { if (_consumerSecret.Length == 0) { _consumerSecret = GuiEnvironment.TwitterAPISecret; //"7L8JDh2PyhIUITC2yUKU4xEV0TZR3UUPW9GMKxoYShg1ePNryD"; _phrases.Node("CONSUMER_SECRET").PropertyForCulture("TEXT", "***"); } return _consumerSecret; } set { _consumerSecret = value; } } public string Token { get { return _token; } set { _token = value; } } public string TokenSecret { get { return _tokenSecret; } set { _tokenSecret = value; } } #endregion /// /// Get the link to Twitter's authorization page for this application. /// /// The url with a valid request token, or a null string. public string AuthorizationLinkGet() { string ret = null; string response = oAuthWebRequest(Method.POST, REQUEST_TOKEN, String.Empty); //the most current instructions show this is now a POST(not GET) //https://developer.twitter.com/en/docs/basics/authentication/api-reference/request_token if (response.Length > 0) { //response contains token and token secret. We only need the token. NameValueCollection qs = HttpUtility.ParseQueryString(response); if (qs["oauth_token"] != null) { ret = AUTHORIZE + "?oauth_token=" + qs["oauth_token"]; } } return ret; } /// /// Exchange the request token for an access token. /// /// The oauth_token is supplied by Twitter's authorization page following the callback. /// Verification string needed to ultimately receive an access token public void AccessTokenGet(string authToken, string verifier) { this.Token = authToken; this.Verifier = verifier; string response = oAuthWebRequest(Method.GET, ACCESS_TOKEN, String.Empty); if (response.Length > 0) { //Store the Token and Token Secret NameValueCollection qs = HttpUtility.ParseQueryString(response); if (qs["oauth_token"] != null) { this.Token = qs["oauth_token"]; } if (qs["oauth_token_secret"] != null) { this.TokenSecret = qs["oauth_token_secret"]; } } } /// /// Submit a web request using oAuth. /// /// GET or POST /// The full url, including the querystring. /// Data to post (querystring format) /// The web server response. public string oAuthWebRequest(Method method, string url, string postData) { string outUrl = ""; string querystring = ""; string ret = ""; //Setup postData for signing. //Add the postData to the querystring. if (method == Method.POST) { if (postData.Length > 0) { //Decode the parameters and re-encode using the oAuth UrlEncode method. NameValueCollection qs = HttpUtility.ParseQueryString(postData); postData = ""; foreach (string key in qs.AllKeys) { if (postData.Length > 0) { postData += "&"; } qs[key] = HttpUtility.UrlDecode(qs[key]); qs[key] = this.UrlEncode(qs[key]); postData += key + "=" + qs[key]; } if (url.IndexOf("?") > 0) { url += "&"; } else { url += "?"; } url += postData; } } Uri uri = new Uri(url); string nonce = this.GenerateNonce(); string timeStamp = this.GenerateTimeStamp(); //Generate Signature string sig = this.GenerateSignature("tw",uri, this.ConsumerKey, this.ConsumerSecret, this.Token, this.TokenSecret, this.Verifier, method.ToString(), timeStamp, nonce, out outUrl, out querystring); querystring += "&oauth_signature=" + HttpUtility.UrlEncode(sig); //Convert the querystring to postData if (method == Method.POST) { postData = querystring; querystring = ""; } if (querystring.Length > 0) { outUrl += "?"; } ret = WebRequest(method, outUrl + querystring, postData); return ret; } /// /// Web Request Wrapper /// /// Http Method /// Full url to the web resource /// Data to post in querystring format /// The web server response. public string WebRequest(Method method, string url, string postData) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; //This is a must! see https://twittercommunity.com/t/removing-support-for-legacy-tls-versions-1-0-1-1-on-twitter/126648 HttpWebRequest webRequest = null; StreamWriter requestWriter = null; string responseData = ""; webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest; webRequest.Method = method.ToString(); webRequest.ServicePoint.Expect100Continue = false; webRequest.Headers.Add("oauth_callback", "oob"); //needed for desktop app //webRequest.UserAgent = "Identify your application please."; //webRequest.Timeout = 20000; if (method == Method.POST) { webRequest.ContentType = "application/x-www-form-urlencoded"; //POST the data. requestWriter = new StreamWriter(webRequest.GetRequestStream()); try { requestWriter.Write(postData); } catch { throw; } finally { requestWriter.Close(); requestWriter = null; } } TryWebResponseGet(webRequest, out responseData); webRequest = null; return responseData; } /// /// Process the web response. /// /// The request object. /// /// true if it was possible to get the response from the server correctly and this is returned in responsedata, /// false otherwise. /// public bool TryWebResponseGet(HttpWebRequest webRequest, out string responseData) { StreamReader responseReader = null; responseData = ""; try { responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()); responseData = responseReader.ReadToEnd(); webRequest.GetResponse().GetResponseStream().Close(); responseReader.Close(); responseReader = null; } catch(Exception ex) { LastException = ex; return false; } return true; } } }