Skip to content

How to connect to Esty ? #466

Description

@Niji-Bemani

Hi ! I am trying to use your library to connect to the new Etsy API (v3) that require OAuth2.
I used the Twitter sample, and tried to adapt it for Etsy.

I can generate the authorization url and see the Etsy page to grant access.
However, the redirection fails with this error : Error: Error retrieving token: Invalid authorization header (line 605, file "Service", project "OAuth2"), and I have no idea what part should be changed to make it work.

Here is my code :

var CLIENT_ID = '...';
var CLIENT_SECRET = '...';

/**
 * Authorizes and makes a request to the Etsy API v3
 * OAuth 2.0 Making requests on behalf of users
 * https://developers.etsy.com/documentation/essentials/authentication#step-3-request-an-access-token
 */
function run() {
  var service = getService_();
  if (service.hasAccess()) {
    var url = 'https://api.etsy.com/v3/application/openapi-ping';
    var response = UrlFetchApp.fetch(url, {
      headers: {
        Authorization: 'Bearer ' + service.getAccessToken()
      },
      muteHttpExceptions: true
    });
    var result = JSON.parse(response.getContentText());
    Logger.log(JSON.stringify(result, null, 2));
  } else {
    var authorizationUrl = service.getAuthorizationUrl();
    Logger.log('Open the following URL and re-run the script: %s',
        authorizationUrl);
  }
}

/**
 * Reset the authorization state, so that it can be re-tested.
 */
function reset() {
  getService_().reset();
  PropertiesService.getUserProperties().deleteProperty('code_challenge');
  PropertiesService.getUserProperties().deleteProperty('code_verifier');
}

/**
 * Configures the service.
 */
function getService_() {
  pkceChallengeVerifier();
  var userProps = PropertiesService.getUserProperties();
  return OAuth2.createService('Etsy')
  // Set the endpoint URLs.
      .setAuthorizationBaseUrl('https://www.etsy.com/oauth/connect')
      .setTokenUrl(
          'https://api.etsy.com/v3/public/oauth/token?code_verifier=' + userProps.getProperty('code_verifier'))

  // Set the client ID and secret.
      .setClientId(CLIENT_ID)
      .setClientSecret(CLIENT_SECRET)

  // Set the name of the callback function that should be invoked to
  // complete the OAuth flow.
      .setCallbackFunction('authCallback')

  // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(userProps)

  // Set the scopes to request (space-separated).
      .setScope('address_r address_w')

  // Add parameters in the authorization url
      .setParam('response_type', 'code')
      .setParam('code_challenge_method', 'S256')
      .setParam('code_challenge', userProps.getProperty('code_challenge'))

      .setTokenHeaders({
        'Authorization': 'Basic ' + Utilities.base64Encode(CLIENT_ID + ':' + CLIENT_SECRET),
        'Content-Type': 'application/x-www-form-urlencoded',
      });
}

/**
 * Handles the OAuth callback.
 */
function authCallback(request) {
  var service = getService_();
  var authorized = service.handleCallback(request);
  if (authorized) {
    return HtmlService.createHtmlOutput('Success!');
  } else {
    return HtmlService.createHtmlOutput('Denied.');
  }
}

/**
 * Logs the redict URI to register.
 */
function logRedirectUri() {
  Logger.log(OAuth2.getRedirectUri());
}

/**
 * Generates code_verifier & code_challenge for PKCE
 */
function pkceChallengeVerifier() {
  var userProps = PropertiesService.getUserProperties();
  if (!userProps.getProperty('code_verifier')) {
    var verifier = '';
    var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';

    for (var i = 0; i < 128; i++) {
      verifier += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    var sha256Hash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, verifier);

    var challenge = Utilities.base64Encode(sha256Hash)
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=+$/, '');
    userProps.setProperty('code_verifier', verifier);
    userProps.setProperty('code_challenge', challenge);
  }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions