blowstack logo
  • BlowStack
  • ->
  • Blog
  • ->
  • Authenticate Zoho CRM in serverless - Firebase implementation

Authenticate Zoho CRM in serverless

Firebase implementation

Last update

15 min.
  1. Prepere environment to create Firebase functions.
  2. Install Node.js SDK for Zoho CRM.
  3. Create oauth.js file and convert it into a node module.
  4. Create a new collection to hold Zoho tokens.
  5. Create a function for serverless authentication.
  6. Create a test function to create a lead.

 

 

This serveless Zoho CRM authentication recipe is covered for Firebase functions using Node.js. After reading this article you wil be able to use your serverless functions to make authentication using OAuth 2.0 and make simple calls using SDK for Node.js. To conduct authentication you need to have the Blaze plan activated in your firebase account.

 

Prepere environment to create Firebase functions

 

If you familiar with creating Firebase functions you can skip this block and go directly to the next one.

Find a place in your system to create a new project for Firebase functions. Then install necessary official Firebase tools globally.

npm install -g firebase-tools

 

Then init Firebase project using the just installed tools.

firebase init

 

Seletct Functions: Configure and deploy Cloud Functions option using space.

Firebase initiate a project

Next select a project or create a new one. If you already hosting your app in the Firebase it's good to select that project but it's not necessary. In the next step you will be asked to login. After successfull authentication your Firebase project will be built. Open it in your IDE. The core folder is named functions and from there you will operate and create new functions so change to this folder if you use a IDE console. If not remember to perform any console command from this folder.

 

Install Node.js SDK for Zoho CRM

 

It's a good idea to install official Zoho SDK which will help you with authentiaction and API calls. Install the SDK in the functions folder.

npm install zcrmsdk

 

Then in the index.js file, require this module and add config object.

// functions/index.js

const functions = require('firebase-functions');
const ZCRMRestClient = require('zcrmsdk')

const config = {
 "client_id":"1000.BL2631QMU8G37XWUHUXOLZLRVVEJJH",
 "client_secret":"d96679335576a4737f84b877a14079fa6f2f93b63d",
 "redirect_url":"http://dummy_address.com",
 "user_identifier":"dev@blowstack.com",
 "tokenmanagement":"zohoAuth"
};

 

Provide you own data in the config object. If you don't know from where to get those values, please refer to my previous post about Zoho CRM authentication in Node.js and then having client id and client secret get back to this point of the article to follow next steps of Zoho serverless implementation.

 

The very important in the config is tokenmanagemnt value. It should points to the object which implements three functions required by the SDK. Those functions control how tokens are saved, updated and retrieved when needed. In the next step you are going to create those functions and convert them into a node module.

 

Create oauth.js file and convert it into a node module

 

In the functions folder create a new one and name it i.e zohoAuth. Next in this folder create a file named oauth.js and paste the following code.

 

// functions/zohoAuth/oauth.js

let file_persistence = {};

const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

file_persistence.saveOAuthTokens = function (tokenobject) {
    return new Promise(function (resolve, reject) {
        let tokens = {}

        db.collection('zoho').doc('tokens').update({
            access_token: tokenobject.access_token,
            expires_in: tokenobject.expires_in,
            refresh_token: tokenobject.refresh_token,
        })
            // eslint-disable-next-line promise/always-return
            .then(function (docRef) {
                resolve()
            })
            .catch(function (error) {
                console.error("Error adding document: ", error);

            })
    })
}

file_persistence.getOAuthTokens = function (user_identifier) {
    return new Promise(function (resolve, reject) {
        let tokens = {}

        // eslint-disable-next-line promise/always-return
        db.collection('zoho').doc('tokens').get().then((snapshot) => {
            let data = snapshot.data()
            tokens.access_token = data.access_token
            tokens.refresh_token = data.refresh_token
            tokens.expires_in = data.expires_in
            resolve(tokens)
        }).catch((err) => {
            console.log(err)
            resolve()
        })

    })
}

file_persistence.updateOAuthTokens = function (tokenobject) {
    return new Promise(function (resolve, reject) {

        db.collection('zoho').doc('tokens').update({
            access_token: tokenobject.access_token,
            expires_in: tokenobject.expires_in,
        })
            // eslint-disable-next-line promise/always-return
            .then(function (docRef) {
                resolve()
            })
            .catch(function (error) {
                console.error("Error adding document: ", error);

            })
    })
}

module.exports = file_persistence;

 

The implementation is based on the Firebase database. You don't need to provide any authentication values because it will be called from the Firebase servers. Take a look at presented three methods. They operate on database collection named zoho and document named tokens we will create them in a minute but first convert the functions into a node module.

Change the current folder to zohoAuth folder. Then generate package.json file.

npm init -y

 

Check a newly create package.json file. It should have zohoAuth value in the name key.

Get back to the functions folder. And create a local node module from the zohoAuth folder.

npm install --save ./zohoAuth

 

Now your config object points to the module that realy exists. If you want to do any changes to the functions in the futue do it in the zohoAuth folder inside functions folder not in the node_modules folder.

 

Create a new collection to hold Zoho tokens

 

The newly created module refers to a database document and collection that don't exist. Let's fix this now!

Go to the Firebase panel and then to the database tab. Create a new collection named zoho and then a new document named tokens (tokens name instread of autogenerated id). Newly created document should have three String empty fields: access token, expires in and refresh token.

 

Firestore Zoho tokens collection

 

Let's make sure than only authorised services and programmers can read and access tokens data. Go to the rules tab and make tokens collection inaccessible for read and write. 

Firebase rules menu

 

To compare you can see than paintings databse is accessible for anybody but nobody can make changes to (this way you can keep public data for your app in the database).

 

Firebase Firestore permission rules for tokens

 

Create a function for serverless authentication

 

Time to pack all things up into the firebase function which generate access tokens for us. Go to the index.js file and paste the code posted below.

 

...
exports.renderTokens = functions.https.onRequest((request, response) => {

 var grant_token = request.query.grant_token;

 // eslint-disable-next-line promise/always-return
 ZCRMRestClient.initialize(config).then(function () {
  // eslint-disable-next-line promise/always-return
  ZCRMRestClient.generateAuthTokens(config.user_identifier, grant_token).then(function (auth_response) {
   console.log("access token :" + auth_response.access_token);
   console.log("refresh token :" + auth_response.refresh_token);
   console.log("expires in :" + auth_response.expires_in);
  }).catch(e => {
   console.log(e)

  });

  return response.send('OK')

 }).catch(e => {
  console.log(e)
 })
});

 

This implementation is realy straightforward and uses the SDK to generate tokens. Thanks to zohoAuth functions the process is fully covered. Time to test if the function triggered by i.e Postman readly generates our tokens. But first deploy your work to the Firebase using the console.

firebase deploy

 

After deploying there will be shown an Function URL. Copy it and paste to the Postman. Remember to generate grant token, if you don't know what it is once again please refer to the previous article for Node.js impelmentation and get back with the grant token. In the postman make a call and add a key with the name grant_token and paste into value of your previously generated grant token. The generating process can take a while. Check after few minutes if the docuement in the database changed if so you can proceed to test the API using an example call.

 

Postman Zoho CRM Serveless token generation

 

Create a lead function

 

Let's create a second function to check whether our service inserting a data to the Zoho CRM. In the index.js add the following function.

 

// functions/index.js

...

exports.lead = functions.https.onRequest((request, response) => {
 
 // eslint-disable-next-line promise/always-return
 ZCRMRestClient.initialize(config).then(function()//Use ZCRMRestClient.initialize(configJson).then(function() for configuration array
 {
  let input = {}
  input.module = 'Leads';
  
  input.body = {
   "data": [{
    "First_Name": 'My first name',
    "Last_Name": 'Last name',
    "Email": 'example@example.com',
    "Description": 'description',
   }]
  };

  // eslint-disable-next-line promise/always-return
  ZCRMRestClient.API.MODULES.post(input).then(function(response){
   console.log(response)
  }).catch(e => {
   return e;
  })

  console.log(response);
  return response.send('OK')

 }).catch(e => {
  return e;
 })
});

 

Then deploy your code to the firebase and call the URL in the Postman. Check your Zoho CRM account later to see if the lead has been inserted correctly.

 

Now that you understand how to authenticate and make the Zoho CRM API calls using serverless environment you can easily expand the basic functionality using other functions. Remember that Postman by default doesn't use CORS so your calls won't be blocked but this can be an issue in your app. In such case you will have to pass proper header allowing executing url from firebase domain.

Recent posts

BlowStack 2021
Portfolio Cheat
sheets