Fetching data from Xero's API using Google Apps Script and an Apps Script OAuth 2.0 Library

38 Views Asked by At

I keep getting a 403 HTTP error when running the getXeroAPI() function below, after having run the logAuthorizationUrl() function and authenticating using the logged Auth. URL.

APPS SCRIPT

var OAUTH2_CLIENT_ID = 'XYZ';
var OAUTH2_CLIENT_SECRET = 'XYZ';
var OAUTH2_CALLBACK = 'https://script.google.com/macros/d/{SCRIPT ID}/usercallback';
var XERO_TENANT_ID = 'XYZ'; // Required for some API calls

/**
 * Creates an OAuth2 service for the Xero API.
 */
function getXeroService() {
  return OAuth2.createService('xero')
      // Set the endpoint URLs.
      .setAuthorizationBaseUrl('https://login.xero.com/identity/connect/authorize')
      .setTokenUrl('https://identity.xero.com/connect/token')

      // Set the client ID and secret.
      .setClientId(OAUTH2_CLIENT_ID)
      .setClientSecret(OAUTH2_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(PropertiesService.getUserProperties())

      // Set the scopes required for your application.
      .setScope('openid profile email accounting.transactions.read accounting.journals.read')
      
      // Set the grant type
      .setGrantType('authorization_code');
}


/**
 * Handles the OAuth callback.
 */
function authCallback(request) {
  var xeroService = getXeroService();
  var isAuthorized = xeroService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else {
    return HtmlService.createHtmlOutput('Denied. You can close this tab');
  }
}

/**
 * Logs the redirect URI to register in Xero app settings.
 */
function logRedirectUri() {
  var service = getXeroService();
  Logger.log(service.getRedirectUri());
}


/**
 * Checks if the service is authorized and logs the authorization URL if it's not.
 */
function checkAuth() {
  var service = getXeroService();
  if (!service.hasAccess()) {
    Logger.log('Authorize this script by visiting this url: ', service.getAuthorizationUrl());
  } else {
    Logger.log('The script is already authorized.');
  }
}

function logAuthorizationUrl() {
  var service = getXeroService();
  if (!service.hasAccess()) {
    var authorizationUrl = service.getAuthorizationUrl();
    Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
  }
}

/*
 * Example function that makes a call to Xero's API.

function getXeroData() {
  var service = getXeroService();
  if (service.hasAccess()) {
    var url = 'https://api.xero.com/api.xro/2.0/Journals'; // Example endpoint
    var response = UrlFetchApp.fetch(url, {
      headers: {
        'Authorization': 'Bearer ' + service.getAccessToken(),
        'xero-tenant-id': XERO_TENANT_ID
      }
    });
    var result = JSON.parse(response.getContentText());
    Logger.log(result);
  } else {
    Logger.log('The script is not yet authorized.');
  }
}
*/


function callXeroApi() {
  var service = getXeroService();
  if (service.hasAccess()) {
    var url = 'https://api.xero.com/api.xro/2.0/Journals';
    var options = {
      method: 'GET', // Explicitly set the HTTP request method to GET
      headers: {
        'Authorization': 'Bearer ' + service.getAccessToken(),
        'Accept': 'application/json'
      },
      muteHttpExceptions: true // Optional: Prevents exceptions for HTTP error responses (e.g., 404, 500)
    };
    var response = UrlFetchApp.fetch(url, options);
    
    // Check for success response code (e.g., 200 OK)
    if (response.getResponseCode() == 200) {
      var json = JSON.parse(response.getContentText());
      Logger.log(json);
    } else {
      Logger.log('Error fetching data from Xero API. Response code: ' + response.getResponseCode());
    }
  } else {
    Logger.log('No access token available.');
  }
}

I keep getting a 403 HTTP error when running the getXeroAPI() function below, after having run the logAuthorizationUrl() function and authenticating using the logged Auth. URL. What should I do to stop getting this error?

I keep getting a 403 HTTP error when running the getXeroAPI() function below, after having run the logAuthorizationUrl() function and authenticating using the logged Auth. URL. What should I do to stop getting this error?

1

There are 1 best solutions below

0
sallyhornet On

I can see you have a client id and secret in this thread; for security reasons please can you edit this post to redact them and then generate a new secret in developer.xero.com.

When you make your request to the journals endpoint (and other endpoints) please can you make sure that you include the tenant id in the request header, this is missing at the moment.

If you still have an issue, can you raise a case with Xero using this form