Node Token Refresh for Data API call

Hey Guys,

 

In an attempt to learn JavaScript and Node, I’m looking to created a script used to retrieve dataset details. My first script attempt is used to automate a token refresh. I'd like to use this refreshed token as an object that can be parsed and called into a second request capturing the dataset details I’m looking for.

 

I’ve successfully connected to DOMO, and made the refresh call. I’ve confirmed the script works by console logging the value within Node. The problem I’m having is capturing the response in an Object, Array, or Variable, to parse and push to the Dataset request. Researching, I found due to the asynchronous nature of JavaScript and Node, a promise or callback must be used to capture the results. I’ve decided to take the promise approach and I’m happy with the code yet no matter what I research, I cannot find a way to capture the response “access_token” in any type of object.

 

My understanding is that as the code executes the variable assignment moves to the top of the execution stack and is assigned prior to the promise completion based on Nodes single thread approach.

 

Basic understanding: (this is just my currect understanding, I can be 100% incorrect)

The code is called and executed top to bottom, left to right. As the steps complete the stack receives them in order and executes one by one. When the https function is called into the stack, it’s moved to the API or deferred queue and the next step is evaluated.  Once the variable assignment is executed the promise is identified and the value set to promise pending. Once all the steps complete and the promise is satisfied, it’s returned to the stack by the event loop for completion. Since the variable assignment has already been set to pending it’s not refreshed with the actual value.

 

Questions:

  1. Is JavaScript and Node the best tools for the job?
    1. Is calling for a refresh token and using the return value to create a new options object something that’s doable? Seems I can’t find any documentation online (Github, Stack overflow etc..) I’ve asked the question on a few developer forums and internally with our web developers yet no one has been able to help me.
  2. If Node and JavaScript are not suitable, should I be using something like Java or Pythont?
  3. If suitable, can someone please share their code?

 

Below is a the basic approach I’m using to accomplish the task. This is just the call used to capture the refresh token that will later be used to call the dataset desired. I can console.log the value and everything checks out, I’m just unable to assign the value to a reusable object.

 

My code:

//Begin Code

var http = require("https");

var async = require("async");

 

var tokenOptions = {

  "method": "GET",

  "hostname": "api.domo.com",

  "port": null,

  "path": "/oauth/token?grant_type=client_credentials&scope=data%20user",

  "headers": {

              "Accept":"application/json",

              "Authorization": "My request token goes here"

             }

};

                   

  let NewToken = new Promise( function(resolve,reject) {

                      //I will change this to a status evaluation, just wanted to force a true value for discovery.      

                  if(1===1){

                    req = http.request(tokenOptions,async function (res) {

                    var chunks = [];

                    var RequestToken = {};

 

                    res.on("data", function (chunk) {

                    chunks.push(chunk);

                    //console.log(chunks)

                        })

 

                    res.on("end",async function doSomething(res) {

                    body = Buffer.concat(chunks);

                    RequestToken = await JSON.parse(body.toString());

                    resolve(RequestToken.access_token);

                    // console.log(RequestToken.access_token)     

                        })

                    })

                    req.end();

                  }else{

                    reject(err);

                    req.end();

                  }

   });

 

//Used to console.log the resolved value of the request promise.

    NewToken.then(function(){

     console.log(NewToken)

    })

//End Code

 

Thank you for the help, I’ve been researching this for weeks and not able to overcome this issue. I'm thinking my understanding or approach is not correct.

 

Neil Black

Assc Dir Mktg, Optum Corporate

 

Comments

  • Figure I'd reply with a working script.

     

    I was able to call the token refresh and capture the value using a promise. Once the promise is fullfilled the refresh token is passed to a the datset list request. The better approach would be to chain the promise however using Google Dev tools, It helped to walk through the steps and see the values pass between functions.

     

    Anyways hope this helps anyone faced with a simular issue,

    Neil

     

    //Begin Code

    //Include the HTTP module
    //To install use the following command within the Node command prompt
    // npm install http -g
    var http = require("https");

    //Token options used in the HTTP request.
    var tokenOptions = {
    "method": "GET",
    "hostname": "api.domo.com",
    "port": null,
    "path": "/oauth/token?grant_type=client_credentials&scope=data%20user",
    "headers": {
    "Accept":"application/json",
    //The below access token can be obtained by navigating to the following URL and entering your
    //Client ID and Secret, the resulting access token can be entered below, the "Basic" needs to stay
    //prior to the actual token key.
    // "Basic + Token"
    //URL: https://developer.domo.com/explorer#!/auth
    "Authorization": "Basic YourTokenGoesHere"
    }
    };

    //Create a promise to handle the async HTTP request.
    //This request uses the above token to request a updated token used to request the dataset listing.
    //The tokens expire so a new request token must be requested.
    var newRequest = new Promise(function(resolve,reject){
    //1=1 is a defult placeholder that always results in true. I'll add some option handeling
    if(1===1){
    //submit the actual request
    req = http.request(tokenOptions,function (res,error) {
    var chunks = [];
    var RequestToken = {};

    res.on("data", function (chunk) {
    chunks.push(chunk);
    })

    res.on("end",function (res) {
    body = Buffer.concat(chunks);
    RequestToken = JSON.parse(body.toString());
    resolve (RequestToken);
    })
    })
    //I'd like to capture errors here however, I believe the res.on('error') might be better
    //testing the catch using an incorrect URL doesnt invoke the error.
    }else{
    console.log("An error occured requesting the refresh token:" + err); }
    req.end();
    });

    //call the promise forcing the process to wait for the updated token
    var RequestResults = function(){
    newRequest
    .then(function (resolve){
    //update the token options for the datset request.
    //URL is updates and the new token is provided
    tokenOptions.path = '/v1/datasets';
    tokenOptions.headers.Authorization = 'bearer ' + resolve.access_token
    //************************Adding new promise to handle dataset request**************
    var DatasetRequest = new Promise(function(resolve,reject){
    if(1===1){

    req = http.request(tokenOptions,function (res,error) {
    var chunks = [];
    var RequestToken = {};

    res.on("data", function (chunk) {
    chunks.push(chunk);
    })

    res.on("end",function (res) {
    body = Buffer.concat(chunks);
    RequestToken = JSON.parse(body.toString());
    // console.log(tokenOptions);
    console.log(RequestToken);
    console.log(RequestToken.length)
    resolve (RequestToken);
    })
    })

    }else{
    console.log("An error occured requesting the refresh token:" + err); }
    req.end();
    });
    })
    .catch(function(reject){
    console.log("An error was thrown!:" + reject);
    })
    };
    //Call the initial promise so that the Token is avaliable for the second call
    RequestResults()

This discussion has been closed.