본문 바로가기
C#

19# C#에서 Twitter 계정 검증

by NaHyungMin 2019. 5. 2.

기본 계정 연동 정보는 구글과 비슷하다.

클라이언트에서 로그인을 하고 구글의 경우 ID를 트위터의 경우 auth, secret_key를 준다.

 

아래 oauth_token과 oauth_token_secert을 얻었으면 아래의 url에 정보를 전송해야 한다.

 

아래는 해외 사이트 찾아서 만든 테스트 코드.

 

using System;

namespace twitter

{

    class Program

    {

        private const string API_KEY = "server_api_key";

        private const string API_SECRET_KEY = "server_secert_key";

        private const string CLIENT_TOKEN = "client_token";

        private const string CLIENT_SECRET_KEY = "client_secret_key";

 

        static void Main(string[] args)

        {

            TwitterUser twitterUser = new TwitterUser();

            twitterUser.GetTwitterUser(API_KEY, API_SECRET_KEY, CLIENT_TOKEN, CLIENT_SECRET_KEY);

        }

    }

}

 

main.cs

using System;

using System.Collections.Generic;

using System.Globalization;

using System.Net;

using System.Text;

using Newtonsoft.Json.Linq;

 

namespace twitter

{

    public class TwitterUser

    {

        private const string OAuthVersion = "1.0";

 

        public string GetTwitterUser(string ConsumerKey, string ConsumerSecret, string authToken, string secretToken)

        {

            // see all comments from GenerateTokenUrl as they apply here as well

            string Nonce = GenerateNonce();

            string timestamp = GenerateTimeStamp();

            TwitterUrls TwitterUrls = new TwitterUrls("https://api.twitter.com/1.1/account/verify_credentials.json");

            List<KeyValuePair<string, string>> Parameters = new List<KeyValuePair<string, string>>();

            Parameters.Add(new KeyValuePair<string, string>("include_email""false"));

            Parameters.Add(new KeyValuePair<string, string>("oauth_consumer_key", ConsumerKey));

            Parameters.Add(new KeyValuePair<string, string>("oauth_nonce", Nonce));

            Parameters.Add(new KeyValuePair<string, string>("oauth_signature_method""HMAC-SHA1"));

            Parameters.Add(new KeyValuePair<string, string>("oauth_timestamp", timestamp));

            Parameters.Add(new KeyValuePair<string, string>("oauth_token", authToken));

            Parameters.Add(new KeyValuePair<string, string>("oauth_version", OAuthVersion));

            string signature = TwitterUrls.GenerateSignature(ConsumerSecret, Parameters, secretToken);

            Parameters.Insert(3, new KeyValuePair<string, string>("oauth_signature", signature));

 

            string retVal = string.Empty;

 

            string url = TwitterUrls.GenerateCallingUrls(Parameters);

 

            using (WebClient client = new WebClient())

            {

                retVal = client.DownloadString(url);

                JObject product = JObject.Parse(retVal);

 

                string id = product["id"].ToString();

            }

            return retVal;

        }

 

        private string GenerateNonce()

        {

            // found this solution here: http://www.i-avington.com/Posts/Post/making-a-twitter-oauth-api-call-using-c

            return Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture)));

        }

 

        private string GenerateTimeStamp()

        {

            // this just returns a unix epoch timestamp

            var _timeSpan = DateTime.UtcNow - new DateTime(197011000);

            var _oathTimestamp = Convert.ToInt64(_timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);

            return _oathTimestamp.ToString();

        }

    }

}

 

TwitterUser.cs

 

using System;

using System.Collections.Generic;

using System.Security.Cryptography;

using System.Text;

 

namespace twitter

{

    public class HashHMac

    {

        public string CreateHMacHash(string key, string message)

        {

            // found this solution here: http://stackoverflow.com/questions/8780261/hmc-sha1-hash-java-producing-different-hash-output-than-c-sharp

            HMAC hasher = new HMACSHA1(Encoding.UTF8.GetBytes(key));

            byte[] data = hasher.ComputeHash(Encoding.UTF8.GetBytes(message));

            return Convert.ToBase64String(data);

        }

    }

}

 

HashHMac.cs

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace twitter

{

    public class TwitterUrls

    {

        string _EndPointUrl = string.Empty;

        URLEncoder urlEncoder = new URLEncoder();

        public TwitterUrls(string EndPointUrl)

        {

            _EndPointUrl = EndPointUrl;

        }

        public string GenerateSignature(string ConsumerSecret, List<KeyValuePair<string, string>> Parameters, string TokenSecret = null)

        {

 

            string SignatureInner = string.Empty;

            // start the string to be included in the signature with "GET&" ... again just modeling this after the PHP translation

            string Signature = "GET&";

            // the first & is not urlencoded

            Signature += urlEncoder.UrlEncode(_EndPointUrl) + "&";

            // loop over the parameters and add them to the signatures string

            foreach (KeyValuePair<string, string> item in Parameters)

            {

                if (item.Key == "oauth_callback")

                {

                    // the callback url needs to be encoded twice, so do it first now

                    SignatureInner += item.Key + "=" + urlEncoder.UrlEncode(item.Value) + "&";

                }

                else

                {

                    SignatureInner += item.Key + "=" + item.Value + "&";

                }

            }

            // strip off the last "&"

            SignatureInner = SignatureInner.Substring(0, SignatureInner.Length - 1);

            // url encode the inner signature

            SignatureInner = urlEncoder.UrlEncode(SignatureInner);

            // add the inner signature to the signature

            Signature += SignatureInner;

            // url encode the whole thing and include the token secret as part of the key if it's passed in

            return urlEncoder.UrlEncode(new HashHMac().CreateHMacHash(ConsumerSecret + "&" + (!string.IsNullOrEmpty(TokenSecret) ? TokenSecret : ""), Signature));

        }

 

        public string GenerateCallingUrls(List<KeyValuePair<string, string>> Parameters)

        {

            // this method generates the actual url to call, see comments from above method

            string url = _EndPointUrl + "?";

            foreach (KeyValuePair<string, string> item in Parameters)

            {

                if (item.Key == "oauth_callback")

                {

                    url += item.Key + "=" + urlEncoder.UrlEncode(item.Value) + "&";

                }

                else

                {

                    url += item.Key + "=" + item.Value + "&";

                }

            }

            url = url.Substring(0, url.Length - 1);

            return url;

        }

    }

}

 

TwitterUrls.cs

 

using System;

using System.Collections.Generic;

using System.Text;

using System.Text.RegularExpressions;

 

namespace twitter

{

    public class URLEncoder

    {

        public string UrlEncode(string url)

        {

            // found this method here: http://www.codeproject.com/Questions/832905/Is-there-any-equivalent-for-rawurlencode-in-Csharp

            Dictionary<string, string> toBeEncoded = new Dictionary<string, string>() { { "%""%25" }, { "!""%21" }, { "#""%23" }, { " ""%20" },

        { "$""%24" }, { "&""%26" }, { "'""%27" }, { "(""%28" }, { ")""%29" }, { "*""%2A" }, { "+""%2B" }, { ",""%2C" },

        { "/""%2F" }, { ":""%3A" }, { ";""%3B" }, { "=""%3D" }, { "?""%3F" }, { "@""%40" }, { "[""%5B" }, { "]""%5D" } };

            Regex replaceRegex = new Regex(@"[%!# $&'()*+,/:;=?@\[\]]");

            MatchEvaluator matchEval = match => toBeEncoded[match.Value];

            string encoded = replaceRegex.Replace(url, matchEval);

            return encoded;

        }

    }

}

 

URLEncoder.cs

 

참조 사이트

https://developer.twitter.com/en/docs/basics/authentication/overview/3-legged-oauth

 

3-legged OAuth

By using Twitter’s services you agree to our Cookies Use. We use cookies for purposes including analytics, personalisation, and ads.

developer.twitter.com

https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials.html

 

GET account/verify_credentials

By using Twitter’s services you agree to our Cookies Use. We use cookies for purposes including analytics, personalisation, and ads.

developer.twitter.com

http://www.burritostand.com/log-in-to-twitter-with-oauth-and-c-sharp-and-get-twitter-user-email