Building a simple Express server with JWT authentication for iFormBuilder API by Sze Wong
Building a simple Express server with JWT authentication for iFormBuilder API by Sze Wong
Here is a link to the original Medium post.
iFormBuilder provides a vast and mature API set for managing all your data. Due to security concerns, the API does not allow Cross-Origin Resource Sharing (CORS). In order for your front-end to access data within iFormBuilder, a simple server is required.
Below is a simple express server that will provide access to your front-end.
STEP 1: Obtain Client_key and Client_secret from iFormBuilder Admin Portal.
Under the [Company] menu, select [API Apps]. You have to be a company admin to have access to this menu.
Then click on [New Client] to create a new API client. Give your client a name, and make sure you select JWT as the authentication type.
Next, you will need to select which user should have API access. When you code authenticates using the client_key and client_secret, the code will inherit all the rights from this user. As a general rule, create a normal user and assign only the forms that you want API access. Do not grant API access to admin users.
With the Client_key and Client_secret, we are ready to code!
STEP 2: Initialize the project
Let’s start from the beginning. Open the terminal and create a project folder
>mkdir api-access-test
>cd api-access-test
>npm init
This creates a vanilla node project.
Now let’s install a few libraries:
npm install --save axios custom-env express jwt-simple moment querystring
Next, fire up your favorite editor. I will be using Visual Studio Code.
STEP 3: Build the Controller class
In the project’s root folder, create a controller class. This will be the main class for managing connections to iFormBuilder
iform-api-controller.js
Starts with setting up all the required libraries
const jwt = require('jwt-simple');
const moment = require('moment');
const axios = require('axios');
const qs = require('querystring');
require('custom-env').env();
Next set up all the required environment variables
const CLIENT_SECRET = process.env.IFORM_CLIENT_SECRET;
const CLIENT_KEY = process.env.IFORM_CLIENT_KEY;
const SERVERNAME = process.env.IFORM_SERVERNAME;
const DOMAIN = process.env.IFORM_DOMAIN;
const PROFILE_ID = process.env.IFORM_PROFILE_ID;
const PAGE_ID=process.env.IFORM_PAGE_ID;const OAUTH_URL = `https://${SERVERNAME}.${DOMAIN}/exzact/api/oauth/token`
const BASE_URL = `https://${SERVERNAME}.${DOMAIN}/exzact/api/v60/profiles/${PROFILE_ID}/pages/${PAGE_ID}/records`
This example assumes you are trying to pull data from iFormBuilder. If you are accessing other API, your BASE_URL will be different.
Notice we are trying to load environment variables.
Let’s set up the env file for development
Create the file: [.env] in the project’s root folder
IFORM_CLIENT_SECRET = "XXX"
IFORM_CLIENT_KEY = "XXX"
IFORM_SERVERNAME = "[servername]"
IFORM_DOMAIN = "iformbuilder.com"
IFORM_PROFILE_ID = 999
IFORM_PAGE_ID=999
Going back to the controller class
We will start by defining the class name
class IFormAPIController{constructor(){
this.accessToken=null;
this.tokenExpiration=Number.MAX_VALUE;
}
The next two functions uses OAuth to authenticate to iFormBuilder using JWT:
async _getAccessToken() {
const expires = moment().add(5, 'minutes').unix();
const timestamp = moment().unix(); let token = jwt.encode({
iss: CLIENT_KEY,
aud: OAUTH_URL,
exp: expires,
iat: timestamp
}, CLIENT_SECRET); const params = {
grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion:token
} const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
} try {
let t = await axios.post(OAUTH_URL, qs.stringify(params), config)
this.accessToken = t.data.access_token;
this.tokenExpiration = moment().add(t.data.expires_in,'seconds').unix(); console.log("Token = "+this.accessToken);
return (this.accessToken)
} catch (err){
if (err.response) {
console.log(err.response.data)
return(err.response.data)
} else if (err.request) {
console.log(err.request)
return(err.request)
} else {
console.log(err)
return(err)
}
}
}async getAccessToken(){
if (!this.accessToken || moment().add(1, 'minutes').unix() > this.tokenExpiration) {
await this._getAccessToken();
}
return this.accessToken;
}
The _getAccessToken function creates a JWT token in order to obtain an access token. The getAccessToken function checks if there is an existing access token and to see if the token has expired. If so, it will call _getAccessToken to obtain a new token, otherwise, it will just return the existing token.
From here on, you can just call getAccessToken() to authenticate.
Next, let’s write a get request to receive data from iFormBuilder.
async getData(field1){ await this.getAccessToken();
let url = `${BASE_URL}?fields=field1${field1?'(="'+field1+'")':''},field2` const config = {
headers: {
'Authorization': 'Bearer ' + this.accessToken
}
} try {
let res = await axios.get(url,config)
console.log(res.data)
return (res.data)
} catch (err){
if (err.response) {
return(err.response.data)
} else if (err.request) {
return(err.request)
} else {
return(err)
}
}
}}//Close classmodule.exports = IFormAPIController;
This function illustrates how to send a get request to the iFormBuilder API. It pulls 2 fields: field1 and field2, with field1 being a parameter one can search from. See iFormBuilder API documentation for other API url.
POST, PUT, and DELETE request takes similar forms.
Now that we have the controller done, we will create an Express router.
The goal of the router is to route HTTP traffic to the controller and return data back to the client.
Create the file [iform-router.js]:
const IFormAPIController = require('./iform-api-controller');
const express = require('express');class IFormAPIRouter{ constructor(){
this.init();
this.controller = new IFormAPIController();
} init(){
this.router = express.Router();
this.router.get('/', async (req, res) => {
console.log("GET")
console.log(req.query);
let field1 = req.query['field1']
try {
let data = await this.controller.getData(field1);
res.send(data); } catch (err){
console.log("ERR In ROUTER")
console.log(err.message)
res.send('ERROR:'+err.message) } }) }}module.exports = IFormAPIRouter;
This router routes any get quests to the ‘/’ path to the controller. If you want to handle other HTTP requests, you will create additional routes.
var express = require('express')
var bodyParser = require('body-parser')
var path = require('path');
var IFormAPIRouter = require('./iform-api-router');
require('custom-env').env()// declare a new express app
var app = express()
app.use(bodyParser.json())const apiRouter = new IFormAPIRouter();
app.use('/api', apiRouter.router)app.listen(3000, function() {
console.log("App started")
});
To start the server,
>node index.js
Now you should be able to point your browser, or your frontend, to HTTP://localhost:3000/api?field1=value
-
Really Helped Alot.
For More Info Visit: https://subapks.com/netboom-mod-apk/
Please sign in to leave a comment.
Comments
1 comment