1

Having failed miserably using C# code to get an Etsy OAuth 2 token, I resorted to using Postman for the initial request figuring that it would then be a simple matter of requesting a refresh token as and when needed. So, from Postman, all good, I can sign in and grant access, which then causes Etsy to respond with a shortlived access token (and a refresh token to use to request another access token without having to go through the whole grant process again).

However, I cannot figure out how to get another access token using this refresh token as Etsy keeps on responding with grant_type is required.

OK, the initial response from Postman following the success grant access is:

{
    "access_token": "<initial-access-token-from_Etsy>",
    "token_type": "Bearer",
    "expires_in": 3600,

    "refresh_token": "<my-refresh-token>"
}

And following their docs to request a refresh OAuth token, it implies that all I need to do is to make a POST request to https://openapi.etsy.com/v3/public/oauth/token, adding the following parameters to the JSON body with content type: application/x-www-form-urlencoded:

{
   "grant_type": "refresh_token",
   "client_id": "<my-client-API-string>",
   "refresh_token": "<my-refresh-token>"
}

Thus, setting all this up in Postman and looking at the generated code for the request gives:

var client = new RestClient("https://openapi.etsy.com/v3/public/oauth/token");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("x-api-key", "<my-client-API-string>");*
request.AddParameter("grant_type", "refresh_token");
request.AddParameter("client_id", "<my-client-API-string>");
request.AddParameter("refresh_token", "<my-refresh-token>");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

*NOTE - I had to add in the header the parameter x-api-key otherwise it would fail with "error": "Missing x-api-key header or client_id"

Alas, the response from Etsy is always

{
    "error": "invalid_request",
    "error_description": "grant_type is required"
}

This post guided me in making the initial request.

Why is it moaning about grant_type when it's in the body as requested!?!?!?

err1
  • 499
  • 9
  • 22
  • 1
    Don't add them as parameters. Instead use HttpContent with a KVP as so: HttpContent content = new FormUrlEncodedContent(myKeyValuePair); – GH DevOps Jan 31 '22 at 16:14
  • 1
    Try creating a dynamic object with the body parameters and use `addJsonBody` instead of setting the parameters one by one. – Abdelkrim Jan 31 '22 at 16:14

2 Answers2

4

Solved!: I had to first figure out what @GH DevOps was on about (didn't try @Abdelkrim Bournane's) but eventually came up with the following solution:

public async void RenewRefreshToken()
{
    string contents;
    string url = "https://openapi.etsy.com/v3/public/oauth/token";
    Dictionary<string, string> data = new Dictionary<string, string>
    {
        { "grant_type", "refresh_token" },
        { "client_id", "<my-client-API-string>>" },
        { "refresh_token", "<my-refresh-token>" }
    };

    var httpClient = new HttpClient();
    var response = await httpClient.PostAsync(url, new FormUrlEncodedContent(data));

    //
    // Response from Etsy will be as documented on their website: https://developer.etsy.com/documentation/essentials/authentication/#requesting-a-refresh-oauth-token
    //
    // access token will be valid for another 1hr
    // Thereater, renew again using the returned refresh token
    //
    contents = await response.Content.ReadAsStringAsync();
}

The response is JSON containing the new access token and refresh token**.

{
    "access_token":"<my-new-access-token>",
    "token_type":"Bearer",
    "expires_in":3600,
    
    "refresh_token":"<my-new-refresh-token>"
}
    
  • EDIT 2022-02-09 *

** Please note that when you renew the Access Token, that the response is a new Access Token (which is valid for 1 hr from time of issue) AND, confusingly to me at least, a new Refresh Token (which is valid for another 90 days from date and time of issue). Therefore, you can keep on collecting and using these Refresh Tokens so long as they have not expired!

err1
  • 499
  • 9
  • 22
  • So, no matter what, each new token will only have a max lifespan of 1 hour ? Does that mean that we will have to keep constantly refreshing the access token all the time? – faniva Apr 14 '22 at 17:18
0
Error401 error = mapper.readValue(response.getBody(), Error401.class);
Unirest.setTimeouts(0, 0);
response = Unirest.post(endpoint.concat("public/oauth/token"))
    .field("grant_type", "refresh_token")
    .field("client_id", properties.getProperty("x-api-key"))
    .field("refresh_token", properties.getProperty("access.refresh.token"))
    .asString();
RefreshToken refreshToken = mapper.readValue(response.getBody(), 
    RefreshToken.class);
properties.setProperty("access.token", refreshToken.getAccess_token());
properties.setProperty("access.refresh.token", refreshToken.getRefresh_token());
properties.storeToXML(new FileOutputStream(new File("src/main/resources/config/oauth.xml")),"Etsy Desktop Management Tool v1",
Charset.forName("UTF-8"));
JOptionPane.showMessageDialog(rootPane, error.getError_description() + "\nAccess Token Refreshed !");
Umar Draz
  • 1
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 15 '23 at 22:14