Etsy oauth authentication c# RestSharp

6.1k views Asked by At

I'm trying to do the sample Authorized Request (or anything with Etsy's api that requires authentication) given in their documentation. The response I get is "oauth_problem=token_rejected".

I used this SO answer along with the OAuth base that benSharper linked to.

I've looked at this and this, and others. One of them used https://sandbox.https://openapi.etsy.com/v2 and when I tried that, the exception was "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel." I deployed to my server (which is https) and still the same response.

Just can't seem to make it work. What am I missing?

Here's my code:

public class AuthorizedRequestHelper
    {
        string baseUrl = "https://openapi.etsy.com/v2";
        string relativePath = "/oauth/scopes";
        string oauth_consumer_key = "xxx";
        string consumerSecret = "xxx";
        string oauth_token = "xxx";
        string oauth_token_secret = "xxx";

        public void test()
        {
            var restClient = new RestClient(baseUrl);
            OAuthBase oAuth = new OAuthBase();

            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string normalizedUrl;
            string normalizedRequestParameters;

            string sig = oAuth.GenerateSignature(new Uri(baseUrl + relativePath), oauth_consumer_key, consumerSecret, oauth_token, oauth_token_secret, "GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);


            var request = new RestRequest(relativePath);
            request.Resource = string.Format(relativePath);
            request.Method = Method.GET;

            request.AddParameter("oauth_consumer_key", oauth_consumer_key);
            request.AddParameter("oauth_token", oauth_token);
            request.AddParameter("oauth_nonce", nonce);
            request.AddParameter("oauth_timestamp", timeStamp);
            request.AddParameter("oauth_signature_method", "HMAC-SHA1");
            request.AddParameter("oauth_version", "1.0");
            request.AddParameter("oauth_signature", sig);

            IRestResponse irestResponse = restClient.Execute(request);
            var content = irestResponse.Content;
            // content = oauth_problem=token_rejected
        }
    }  

Any help would be greatly appreciated.

1

There are 1 answers

10
MikeT On BEST ANSWER

Figured out what I was missing. I was missing Obtaining Token Credentials, which are the permanent tokens you need to access protected resources.

Had trouble wrapping my head around OAuth, RestSharp, and Etsy's implementation all at once. Didn't need the OAuthBase, RestSharp takes care of that.

Note that the appKey and sharedSecret become consumerKey and consumerSecret when making OAuth calls with RestSharp.

Here's working code:

    /// <summary>
    /// RestSharp documentation: https://github.com/restsharp/RestSharp/wiki
    /// </summary>
    public class Etsy_portal
    {
        Uri BASE_URL = new Uri("https://openapi.etsy.com/v2/");

        string appKey;
        string sharedSecret;
        RestClient restClient;

        private string[] _permissions_array;
        public string Permissions
        {
            get { return string.Join(" ", _permissions_array); }
        }

        public Etsy_portal(string appKey_, string sharedSecret_)
        {
            appKey = appKey_;
            sharedSecret = sharedSecret_;

            restClient = new RestClient(BASE_URL);

            //todo move permissions to Web.config
            _permissions_array = new string[] { "listings_r", "listings_w", "listings_d", "shops_rw" };
        }

        public string GetConfirmUrl(out string oauth_token, out string oauth_token_secret, string callbackUrl_ = null)
        {
            restClient.Authenticator = OAuth1Authenticator.ForRequestToken(appKey, sharedSecret, callbackUrl_ ?? "oob");

            RestRequest restRequest = new RestRequest("oauth/request_token", Method.POST);

            restRequest.AddParameter("scope", Permissions);

            IRestResponse response = restClient.Execute(restRequest);

            if (response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                oauth_token = null;
                oauth_token_secret = null;
                return null;
            }

            NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(response.Content);

            oauth_token = queryString["oauth_token"];
            oauth_token_secret = queryString["oauth_token_secret"];

            return queryString["login_url"];
        }

        public void ObtainTokenCredentials(string oauth_token_temp_, string oauth_token_secret_temp_, string oauth_verifier_, out string permanent_oauth_token_, out string permanent_oauth_token_secret_)
        {
            //consumerKey is the appKey you got when you registered your app, same for sharedSecret
            restClient.Authenticator = OAuth1Authenticator.ForAccessToken(appKey, sharedSecret, oauth_token_temp_, oauth_token_secret_temp_, oauth_verifier_);

            RestRequest restRequest = new RestRequest("oauth/access_token", Method.GET);
            IRestResponse irestResponse = restClient.Execute(restRequest);

            NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(irestResponse.Content);

            permanent_oauth_token_ = queryString["oauth_token"];
            permanent_oauth_token_secret_ = queryString["oauth_token_secret"];
        }

        public string GetScopes(string accessToken_, string accessTokenSecret_)
        {
            restClient.Authenticator = OAuth1Authenticator.ForProtectedResource(appKey, sharedSecret, accessToken_, accessTokenSecret_);

            RestRequest restRequest = new RestRequest("oauth/scopes", Method.GET);

            IRestResponse irestResponse = restClient.Execute(restRequest);

            return irestResponse.Content;
        }
    }

Pseudo code (with callback):

  1. Construct an Etsy_portal object
  2. Call GetConfirmUrl, provide a callback URL. The callback will have two query parameters oauth_token and oauth_verifier. Here's an example of a callback function signature:

    [HttpGet] public ActionResult EtsyCallback(string oauth_token, string oauth_verifier)

  3. Save the returned token and secret in a map structure for later retrieval.

  4. Visit the confirmation URL returned from the call to GetConfirmUrl.
  5. In the callback function, use the provided token (the 1st argument in the example above) to look up the secret saved in step 3.
  6. Using the verifier (the 2nd argument to the callback function in the example above), the token and the secret, call ObtainTokenCredentials to get a permanent token and secret.
  7. Save the permanent token and secret, you may discard the verifier, the temporary token and the temporary secret obtained in steps 1-4.