jmawebtech

oauth etsy

Sep 28th, 2014
883
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.28 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Security.Cryptography;
  6. using System.Web;
  7.  
  8. namespace OAuth
  9. {
  10.     public class OAuthBase
  11.     {
  12.  
  13.         /// <summary>
  14.         /// Provides a predefined set of algorithms that are supported officially by the protocol
  15.         /// </summary>
  16.         public enum SignatureTypes
  17.         {
  18.             HMACSHA1,
  19.             PLAINTEXT,
  20.             RSASHA1
  21.         }
  22.  
  23.         /// <summary>
  24.         /// Provides an internal structure to sort the query parameter
  25.         /// </summary>
  26.         protected class QueryParameter
  27.         {
  28.             private string name = null;
  29.             private string value = null;
  30.  
  31.             public QueryParameter(string name, string value)
  32.             {
  33.                 this.name = name;
  34.                 this.value = value;
  35.             }
  36.  
  37.             public string Name
  38.             {
  39.                 get { return name; }
  40.             }
  41.  
  42.             public string Value
  43.             {
  44.                 get { return value; }
  45.             }
  46.         }
  47.  
  48.         /// <summary>
  49.         /// Comparer class used to perform the sorting of the query parameters
  50.         /// </summary>
  51.         protected class QueryParameterComparer : IComparer<QueryParameter>
  52.         {
  53.  
  54.             #region IComparer<QueryParameter> Members
  55.  
  56.             public int Compare(QueryParameter x, QueryParameter y)
  57.             {
  58.                 if (x.Name == y.Name)
  59.                 {
  60.                     return string.Compare(x.Value, y.Value);
  61.                 }
  62.                 else
  63.                 {
  64.                     return string.Compare(x.Name, y.Name);
  65.                 }
  66.             }
  67.  
  68.             #endregion
  69.         }
  70.  
  71.         protected const string OAuthVersion = "1.0";
  72.         protected const string OAuthParameterPrefix = "oauth_";
  73.  
  74.         //
  75.         // List of know and used oauth parameters' names
  76.         //        
  77.         protected const string OAuthConsumerKeyKey = "oauth_consumer_key";
  78.         protected const string OAuthCallbackKey = "oauth_callback";
  79.         protected const string OAuthVersionKey = "oauth_version";
  80.         protected const string OAuthSignatureMethodKey = "oauth_signature_method";
  81.         protected const string OAuthSignatureKey = "oauth_signature";
  82.         protected const string OAuthTimestampKey = "oauth_timestamp";
  83.         protected const string OAuthNonceKey = "oauth_nonce";
  84.         protected const string OAuthTokenKey = "oauth_token";
  85.         protected const string OAuthTokenSecretKey = "oauth_token_secret";
  86.  
  87.         protected const string HMACSHA1SignatureType = "HMAC-SHA1";
  88.         protected const string PlainTextSignatureType = "PLAINTEXT";
  89.         protected const string RSASHA1SignatureType = "RSA-SHA1";
  90.  
  91.         protected Random random = new Random();
  92.  
  93.         protected string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
  94.  
  95.         /// <summary>
  96.         /// Helper function to compute a hash value
  97.         /// </summary>
  98.         /// <param name="hashAlgorithm">The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function</param>
  99.         /// <param name="data">The data to hash</param>
  100.         /// <returns>a Base64 string of the hash value</returns>
  101.         private string ComputeHash(HashAlgorithm hashAlgorithm, string data)
  102.         {
  103.             if (hashAlgorithm == null)
  104.             {
  105.                 throw new ArgumentNullException("hashAlgorithm");
  106.             }
  107.  
  108.             if (string.IsNullOrEmpty(data))
  109.             {
  110.                 throw new ArgumentNullException("data");
  111.             }
  112.  
  113.             byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(data);
  114.             byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
  115.  
  116.             return Convert.ToBase64String(hashBytes);
  117.         }
  118.  
  119.         /// <summary>
  120.         /// Internal function to cut out all non oauth query string parameters (all parameters not begining with "oauth_")
  121.         /// </summary>
  122.         /// <param name="parameters">The query string part of the Url</param>
  123.         /// <returns>A list of QueryParameter each containing the parameter name and value</returns>
  124.         private List<QueryParameter> GetQueryParameters(string parameters)
  125.         {
  126.             if (parameters.StartsWith("?"))
  127.             {
  128.                 parameters = parameters.Remove(0, 1);
  129.             }
  130.  
  131.             List<QueryParameter> result = new List<QueryParameter>();
  132.  
  133.             if (!string.IsNullOrEmpty(parameters))
  134.             {
  135.                 string[] p = parameters.Split('&');
  136.                 foreach (string s in p)
  137.                 {
  138.                     if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix))
  139.                     {
  140.                         if (s.IndexOf('=') > -1)
  141.                         {
  142.                             string[] temp = s.Split('=');
  143.                             result.Add(new QueryParameter(temp[0], temp[1]));
  144.                         }
  145.                         else
  146.                         {
  147.                             result.Add(new QueryParameter(s, string.Empty));
  148.                         }
  149.                     }
  150.                 }
  151.             }
  152.  
  153.             return result;
  154.         }
  155.  
  156.         /// <summary>
  157.         /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
  158.         /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
  159.         /// </summary>
  160.         /// <param name="value">The value to Url encode</param>
  161.         /// <returns>Returns a Url encoded string</returns>
  162.         protected string UrlEncode(string value)
  163.         {
  164.             StringBuilder result = new StringBuilder();
  165.  
  166.             foreach (char symbol in value)
  167.             {
  168.                 if (unreservedChars.IndexOf(symbol) != -1)
  169.                 {
  170.                     result.Append(symbol);
  171.                 }
  172.                 else
  173.                 {
  174.                     result.Append('%' + String.Format("{0:X2}", (int)symbol));
  175.                 }
  176.             }
  177.  
  178.             return result.ToString();
  179.         }
  180.  
  181.         /// <summary>
  182.         /// Normalizes the request parameters according to the spec
  183.         /// </summary>
  184.         /// <param name="parameters">The list of parameters already sorted</param>
  185.         /// <returns>a string representing the normalized parameters</returns>
  186.         protected string NormalizeRequestParameters(IList<QueryParameter> parameters)
  187.         {
  188.             StringBuilder sb = new StringBuilder();
  189.             QueryParameter p = null;
  190.             for (int i = 0; i < parameters.Count; i++)
  191.             {
  192.                 p = parameters[i];
  193.                 sb.AppendFormat("{0}={1}", p.Name, p.Value);
  194.  
  195.                 if (i < parameters.Count - 1)
  196.                 {
  197.                     sb.Append("&");
  198.                 }
  199.             }
  200.  
  201.             return sb.ToString();
  202.         }
  203.  
  204.         /// <summary>
  205.         /// Generate the signature base that is used to produce the signature
  206.         /// </summary>
  207.         /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
  208.         /// <param name="consumerKey">The consumer key</param>        
  209.         /// <param name="token">The token, if available. If not available pass null or an empty string</param>
  210.         /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
  211.         /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
  212.         /// <param name="signatureType">The signature type. To use the default values use <see cref="OAuthBase.SignatureTypes">OAuthBase.SignatureTypes</see>.</param>
  213.         /// <returns>The signature base</returns>
  214.         public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters)
  215.         {
  216.             if (token == null)
  217.             {
  218.                 token = string.Empty;
  219.             }
  220.  
  221.             if (tokenSecret == null)
  222.             {
  223.                 tokenSecret = string.Empty;
  224.             }
  225.  
  226.             if (string.IsNullOrEmpty(consumerKey))
  227.             {
  228.                 throw new ArgumentNullException("consumerKey");
  229.             }
  230.  
  231.             if (string.IsNullOrEmpty(httpMethod))
  232.             {
  233.                 throw new ArgumentNullException("httpMethod");
  234.             }
  235.  
  236.             if (string.IsNullOrEmpty(signatureType))
  237.             {
  238.                 throw new ArgumentNullException("signatureType");
  239.             }
  240.  
  241.             normalizedUrl = null;
  242.             normalizedRequestParameters = null;
  243.  
  244.             List<QueryParameter> parameters = GetQueryParameters(url.Query);
  245.             parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
  246.             parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
  247.             parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
  248.             parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
  249.             parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
  250.  
  251.             if (!string.IsNullOrEmpty(token))
  252.             {
  253.                 parameters.Add(new QueryParameter(OAuthTokenKey, token));
  254.             }
  255.  
  256.             parameters.Sort(new QueryParameterComparer());
  257.  
  258.             normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
  259.             if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
  260.             {
  261.                 normalizedUrl += ":" + url.Port;
  262.             }
  263.             normalizedUrl += url.AbsolutePath;
  264.             normalizedRequestParameters = NormalizeRequestParameters(parameters);
  265.  
  266.             StringBuilder signatureBase = new StringBuilder();
  267.             signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
  268.             signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
  269.             signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
  270.  
  271.             return signatureBase.ToString();
  272.         }
  273.  
  274.         /// <summary>
  275.         /// Generate the signature value based on the given signature base and hash algorithm
  276.         /// </summary>
  277.         /// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param>
  278.         /// <param name="hash">The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method</param>
  279.         /// <returns>A base64 string of the hash value</returns>
  280.         public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash)
  281.         {
  282.             return ComputeHash(hash, signatureBase);
  283.         }
  284.  
  285.         /// <summary>
  286.         /// Generates a signature using the HMAC-SHA1 algorithm
  287.         /// </summary>     
  288.         /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
  289.         /// <param name="consumerKey">The consumer key</param>
  290.         /// <param name="consumerSecret">The consumer seceret</param>
  291.         /// <param name="token">The token, if available. If not available pass null or an empty string</param>
  292.         /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
  293.         /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
  294.         /// <returns>A base64 string of the hash value</returns>
  295.         public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters)
  296.         {
  297.             return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
  298.         }
  299.  
  300.         /// <summary>
  301.         /// Generates a signature using the specified signatureType
  302.         /// </summary>     
  303.         /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
  304.         /// <param name="consumerKey">The consumer key</param>
  305.         /// <param name="consumerSecret">The consumer seceret</param>
  306.         /// <param name="token">The token, if available. If not available pass null or an empty string</param>
  307.         /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
  308.         /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
  309.         /// <param name="signatureType">The type of signature to use</param>
  310.         /// <returns>A base64 string of the hash value</returns>
  311.         public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters)
  312.         {
  313.             normalizedUrl = null;
  314.             normalizedRequestParameters = null;
  315.  
  316.             switch (signatureType)
  317.             {
  318.                 case SignatureTypes.PLAINTEXT:
  319.                     return System.Web.HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
  320.                 case SignatureTypes.HMACSHA1:
  321.                     string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
  322.  
  323.                     HMACSHA1 hmacsha1 = new HMACSHA1();
  324.                     hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));
  325.  
  326.                     return GenerateSignatureUsingHash(signatureBase, hmacsha1);
  327.                 case SignatureTypes.RSASHA1:
  328.                     throw new NotImplementedException();
  329.                 default:
  330.                     throw new ArgumentException("Unknown signature type", "signatureType");
  331.             }
  332.         }
  333.  
  334.         /// <summary>
  335.         /// Generate the timestamp for the signature        
  336.         /// </summary>
  337.         /// <returns></returns>
  338.         public virtual string GenerateTimeStamp()
  339.         {
  340.             // Default implementation of UNIX time of the current UTC time
  341.             TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
  342.             return Convert.ToInt64(ts.TotalSeconds).ToString();
  343.         }
  344.  
  345.         /// <summary>
  346.         /// Generate a nonce
  347.         /// </summary>
  348.         /// <returns></returns>
  349.         public virtual string GenerateNonce()
  350.         {
  351.             // Just a simple implementation of a random number between 123400 and 9999999
  352.             return random.Next(123400, 9999999).ToString();
  353.         }
  354.  
  355.     }
  356. }
Add Comment
Please, Sign In to add comment