Linked Questions

Popular Questions

How to hide confidential information in javascript?

Asked by At

I have some JS code written in ES6, The code is communicating with a third party API using GET, POST requests. I've spent more than 2 weeks writing and studying that code, but now When it is completed I realized that all the confidential information like my AUTH_TOKEN is visible to everyone, I don't want to rewrite the whole code again in PHP. I also tried to store the code at the server side using PHP and then fetching the token through an ajax call, but that too is visible in Networks, anyone can check the response coming from the server.

Is there any way I can hide that AUTH_TOKEN from the public without rewriting the entire code.

Here is how my code looks like

jQuery(document).ready( function($){
  const AUTH_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXX";
  const ajax_url = dtLocal.ajaxurl;
  const SEARCH_PARAM = new URLSearchParams(window.location.search);
  const PROXY_URL = 'https://cors-anywhere.herokuapp.com/';
  let json_data_path = script_vars.json_data_path;
  let page = script_vars.page_slug;

  /***********************************************************Function*********************************************************/
  /*********************************************************Definitions*********************************************************/

  let writeJSONdata = ($, data) => (data.action = "write_api_data_to_file", $.post(ajax_url, data, (resp) => console.log(resp)));

  let getJobOpeningsFromAPI = async ($, auth_token) => {
    const URL = `https://recruit.zoho.com/recruit/private/json/JobOpenings/getRecords?authtoken=${auth_token}&scope=recruitapi`;
    let data;
    await $.get(PROXY_URL+URL).then( resp => {
        data = resp;
    } );
    return data;
  }

  let displayJobOpenings = ($, data) => {
    console.log(data);
    let dataSet = [];
    data.forEach( i=>{
      let jobType = (i.FL.filter( i => i.val === "Job Type" ).length) ? i.FL.filter( i => i.val === "Job Type" )[0].content : "";
      let postingTitle = (i.FL.filter( i => i.val === "Posting Title" ).length) ? i.FL.filter( i => i.val === "Posting Title" )[0].content : "";
      let city = (i.FL.filter( i => i.val === "City" ).length) ? i.FL.filter( i => i.val === "City" )[0].content : "";
      let state = (i.FL.filter( i => i.val === "State" ).length) ? i.FL.filter( i => i.val === "State" )[0].content : "";
      let datePosted = (i.FL.filter( i => i.val === "Date Opened" ).length) ? i.FL.filter( i => i.val === "Date Opened" )[0].content : "";
      let jobID = (i.FL.filter( i => i.val === "JOBOPENINGID" ).length) ? i.FL.filter( i => i.val === "JOBOPENINGID" )[0].content : "";
      let location = `${city}, ${state}`;
        let set = [postingTitle, location, datePosted, jobType, jobID];
        dataSet.push(set);
    } );
    let table = $('#careers_table').DataTable( {
        "fnCreatedRow": function( nRow, aData, iDataIndex ) {
            $(nRow).attr('id', aData[4]);
        },
        data: dataSet,
        columns: [
            { title: "Job Title" },
            { title: "Location" },
            { title: "Date Posted" },
            { title: "Job Type" },
        ],
        "lengthChange": false
    } );

    $('#careers_table tbody').on('click', 'tr', function () {
        let data = table.row( this ).data();
        let jobID = data[4];
        window.location.href = `?jobID=${jobID}`; 
    } );

    /*--------------Filetering------------------------*/
    let locations = table.column( 1 ).data().unique(); //Distinct job locations to put in dropdown
    let jobTypes = table.column( 3 ).data().unique(); //Distinct job types to put in dropdown
    locations.map( i => $('#filter-location').append(`<option value='${i}'>${i}</option>`) );
    jobTypes.map( i => $('#filter-type').append(`<option value='${i}'>${i}</option>`) );

    $('#filter-keyword').on( 'keyup', function () {
        table.search( this.value ).draw();
    } );

    $('#filter-location').on( 'change', function () {
        table.column(1).search( this.value ).draw();
    } );

    $('#filter-type').on( 'change', function () {
        table.column(3).search( this.value ).draw();
    } );
    /*--------------Filetering------------------------*/
  }/*-----displayJobOpenings()-----*/

  let displayJobDetails = ($) => {
    let jobID = SEARCH_PARAM.has('jobID') ? SEARCH_PARAM.get('jobID') : '';
    let jd;
    let markup;

    if(!jobID) return;

    axios.get(json_data_path).then( res => {

      let data = res.data.response.result.JobOpenings.row;
      jd = (data.filter( i => i.FL[0].content === jobID ).length) ? data.filter( i => i.FL[0].content === jobID )[0].FL : "";
      let jobTitle = (jd.filter( i => i.val === "Posting Title" ).length) ? jd.filter( i => i.val === "Posting Title" )[0].content : "";
      let experience = (jd.filter( i => i.val === "Work Experience" ).length) ? jd.filter( i => i.val === "Work Experience" )[0].content : "";
      let numberPositions = (jd.filter( i => i.val === "Number of Positions" ).length) ? jd.filter( i => i.val === "Number of Positions" )[0].content : "";
      let city = (jd.filter( i => i.val === "City" ).length) ? jd.filter( i => i.val === "City" )[0].content : "";
      let state = (jd.filter( i => i.val === "State" ).length) ? jd.filter( i => i.val === "State" )[0].content : "";
      let country = (jd.filter( i => i.val === "Country" ).length) ? jd.filter( i => i.val === "Country" )[0].content : "";
      let jobDescription = (jd.filter( i => i.val === "Job Description" ).length) ? jd.filter( i => i.val === "Job Description" )[0].content : "";

      //let jdesc = jd[31].content;
      let moreInfoMarkup = '<h3>More Info</h3>'+
            '<p><strong>Experience </strong>: '+experience+'</p>'+
            '<p><strong>Number of Positions </strong>: '+numberPositions+'</p>'+
            '<p><strong>Job Location </strong>: '+city+', '+state+'</p>';

      $(".job-title").html(jobTitle);
      $(".job-desc").html(`<h3>Job Description</h3> ${jobDescription}`);
      $(".job-more").html(moreInfoMarkup);
      $("#spanreq").appendTo(".job-req");
      $("#spanben").appendTo(".job-ben");
      //$('#raw-jd').html(jdesc);
      // $('#spandesc').prepend('<h3>Job Description</h3>');
      // $('#raw-jd').prepend('<div class="job-title"><h2>'+jd[9].content+'</h2></div>');
      // $('#raw-jd').append(moreInfoMarkup);
    } ).catch( e=>console.error(`Error occured while fetching data from careers_data.json!`, e));
  }

  let processCandidateDataFromDBtoAPI = ($) => {
    $.post(ajax_url, {
      action: "getCandidateDataFromDB"
    }).done(resp => {
      resp = JSON.parse(resp);
      resp.forEach( i => {
        //console.log(i);
        createCandidate(i).then( r => {
          let jobID = SEARCH_PARAM.has('jobID') ? SEARCH_PARAM.get('jobID') : '';
          i.form_data.candidate_id = candidateID;
          uploadFile($, i);
          associateJobOpening(i.form_data.Job_ID, candidateID);
          //sendRepeateableFields(candidateID, createXMLforRepeatableFields(i));
        } );

      });
    }).fail( e=>console.error(`Error occured while fetching data from wp_db7_forms database table!`, e));
  }

  let createCandidate = async (data) => {
    let xmlString = ''+
      '<Candidates>'+
        '<row no="1">'+
          '<FL val="Source">Zen3 Website</FL>'+
          '<FL val="First Name">'+data.form_data.first_name+'</FL>'+
          '<FL val="Last Name">'+data.form_data.last_name+'</FL>'+
          '<FL val="Email">'+data.form_data.email+'</FL>'+
          '<FL val="Mobile">'+data.form_data.phone_number+'</FL>'+
        '</row>'+
      '</Candidates>';
    const URL = `https://recruit.zoho.com/recruit/private/xml/Candidates/addRecords?authtoken=${AUTH_TOKEN}&scope=recruitapi&duplicateCheck=2&version=4&xmlData=${xmlString}`;

    let request = await axios.post(PROXY_URL+URL).then( i => {
      let xmlString = i.data;
      parser = new DOMParser();
      xmlDoc = parser.parseFromString(xmlString,"text/xml");
      candidateID = xmlDoc.getElementsByTagName("FL")[0].childNodes[0].nodeValue;
      return candidateID;
    } ).catch( e=>console.error(`Error occured while sending candidate data to Zoho API!`, e));

    return request;
  }

  let uploadFile = ($, data) => { //API requests to upload file is handled by PHP
    let action = "upload_candidate_files";
    let request = $.post(ajax_url, { action: action, data: data }).done( resp => {
      console.log(resp);
    }).fail( e=>console.error(`Error occured while Uploading File of candidate to Zoho API!`, e));
  }

  let associateJobOpening = (jobID, candidateID) => {
    const URL = `https://recruit.zoho.com/recruit/private/xml/Candidates/associateJobOpening?authtoken=${AUTH_TOKEN}&scope=recruitapi&jobIds=${jobID}&candidateIds=${candidateID}`;
    axios.post(PROXY_URL+URL).then(i => {
      console.log(i);
    })
  }

  let sendRepeateableFields = (candidateID, xmlData) => {
    const URL = `https://recruit.zoho.com/recruit/internal/xml/Candidates/addTabularRecords?authtoken=${AUTH_TOKEN}&id=${candidateID}&xmlData=${xmlData}`;
    axios.post(PROXY_URL+URL).then( i => console.log(i) ).catch(e => console.error( "Error occured while posting repeatable fields data to Zoho API!", e));
  }

  let createXMLforRepeatableFields = (data) => {
    //console.log(data.form_data);
    let form_data = data.form_data;
    let edFieldCount = parseInt(form_data._wpcf7_groups_count.educational_details);
    let exFieldCount = parseInt(form_data._wpcf7_groups_count.experience_details);

    let xmlString = '<Candidates>';

    if( edFieldCount > 0){
      xmlString += '<FL val="Educational Details">';

      for (let i = 1; i <= edFieldCount; i++) {
        let trno = i;
        trno -= 1;
        let edFrom
        xmlString += '<TR no="'+trno+'">'+
                        '<TL val="Institute / School">'+
                          form_data[`Institute_School__${i}`]+
                        '</TL>'+
                        '<TL val="Major / Department">'+
                          form_data[`Major_Department__${i}`]+
                        '</TL>'+
                        '<TL val="Degree">'+
                          form_data[`Degree__${i}`]+
                        '</TL>'+
                        '<TL val="Duration_From">'+
                          dateFormat(form_data[`ed_from__${i}`])+
                        '</TL>';
        xmlString += (form_data[`ed_to__${i}`]) ? '<TL val="Duration_To">'+dateFormat(form_data[`ed_to__${i}`])+'</TL>':'<TL val="Currently pursuing">false</TL>';

        xmlString += '</TR>';

      }

      xmlString += '</FL>';
    }

    if(exFieldCount > 0){
      xmlString += '<FL val="Experience Details">';

      for (let i = 1; i <= exFieldCount; i++) {
        let trno = i;
        trno -= 1;
        xmlString += '<TR no="'+trno+'">'+
                        '<TL val="Occupation / Title">'+
                          form_data[`Occupation_Title__${i}`]+
                        '</TL>'+
                        '<TL val="Company">'+
                          form_data[`Company__${i}`]+
                        '</TL>'+
                        '<TL val="Summary">'+
                          form_data[`ex_summary__${i}`]+
                        '</TL>'+
                        '<TL val="Work Duration_From">'+
                          dateFormat(form_data[`ex_from__${i}`])+
                        '</TL>';
        xmlString += (form_data[`ex_to__${i}`]) ? '<TL val="Work Duration_To">'+dateFormat(form_data[`ex_to__${i}`])+'</TL>':'<TL val="I currently work here">false</TL>';

        xmlString += '</TR>';

      }

      xmlString += '</FL>';
    } /*exFieldCount end if*/

    xmlString += '</Candidates>';

    return xmlString;
  } /*createXMLforRepeatableFields() end*/

  let dateFormat = (date) => { //convert date to dd-yyyy
    let d = new Date(date);
    let day = d.getDay();
    let year = d.getFullYear();
    day < 10 && '0'+day;
    return day+'-'+year;
  }

  /***********************************************************Function*********************************************************/
  /******************************************************Definitions end*********************************************************/


  /*******************************************************Function***************************************************************/
  /********************************************************Calls***************************************************************/
  if(page==="careers"){
    if (SEARCH_PARAM.has('jobID')) { //functions to run on inner page of job
      let jobID = SEARCH_PARAM.has('jobID') ? SEARCH_PARAM.get('jobID') : '';
      displayJobDetails($);
    } else{ //function ton run on job listing page
      axios.get(json_data_path).then( res => {
         if(res.data){
          displayJobOpenings($, res.data.response.result.JobOpenings.row);
         } else {
           let data = {};
           getJobOpeningsFromAPI($, AUTH_TOKEN).then( i => {
             data.data = i
             writeJSONdata($, data);
             displayJobOpenings($, JSON.parse(data.data).response.result.JobOpenings.row);
           })
           .catch( e=>console.error(`Error occured while fetching data from Zoho API!`, e));
          }
      } ).catch( e=>console.error(`Error occured while fetching data from careers_data.json!`, e));
    }
  }

 processCandidateDataFromDBtoAPI($);

  // axios.get(json_data_path).then((r) => console.log(r));



  /*******************************************************Function***************************************************************/
  /******************************************************Calls end***************************************************************/
});

Related Questions