APPROOV INTEGRATION IN A NODEJS EXPRESS API

Tuesday 05 February 2019 By Paulo Renato

Topics: Integration, Mobile App Authentication

 

Screenshot from 2019-02-04 12-33-28

This walk-though will show us how simple it is to integrate Approov in a current API server using NodeJS and the Express framework.

We will see the requirements, dependencies and a step by step walk-through of the code necessary to implement Approov in a NodeJS Express API.

Before we tackle the integration of Approov we need first to know how Approov validation is processed in the server and how to setup the environment to follow this walk-through.

Note that this article assumes a basic understanding of the Approov mechanics. If you need an overview of that, please read first the Approov in Detail page.

APPROOV VALIDATION PROCESS

Before we dive into the code we need to understand the Approov validation process on the back-end side.

The Approov Token

API calls protected by Approov will typically include a header holding an Approov JWT token. This token must be checked to ensure it has not expired and that it is properly signed with the secret shared between the back-end and the Approov cloud service.

We will use a NodeJS package to help us in the validation of the Approov JWT token.

NOTE

Just to be sure that we are on the same page, a JWT token has 3 parts which are separated by dots and represented as a string in the format of header.payload.signature. Read more about JWT tokens here.

The Custom Payload Claim

A custom payload claim in an Approov token is a base64 encoded sha256 hash of some unique identifier we may want to tie with the Approov token to enhance the security on that request, like an OAUTH2 token, but you are free to use what so ever you may want.

Dummy example for the JWT token middle part, the payload:

{
    "exp": 123456789, # required - the timestamp for when the token expires.
    "pay":"f3U2fniBJVE04Tdecj0d6orV9qT9t52TjfHxdUqDBgY=" # optional - a sha256 hash of the claim, encoded with base64.
}

The custom payload claim in an Approov token is the one in the pay key:

"pay":"f3U2fniBJVE04Tdecj0d6orV9qT9t52TjfHxdUqDBgY="

ALERT:

Please bear in mind that the custom payload claim is not meant to pass application data to the API server, but you can pass a base64 encoded sha256 hash of the data you want to send from the mobile app into the API server and have it hashing the data that was sent as usual on the request and compare it with the custom payload claim base64 sha256 hash to confirm that the integrity of the data was not compromised.

SYSTEM CLOCK

In order to correctly check for the expiration times of the Approov tokens it is very important that the Python Flask server is automatically synchronizing the system clock over the network with an authoritative time source. In Linux this is usually done with an NTP server.

REQUIREMENTS

The example code in this walk-through is based on the Approov Shapes Demo server which runs on NodeJS 10 LTS and Express 4 framework. The full source code can be found in this Github repository.

Docker is required only if you want to use the docker environment provided by the stack bash script, which is a wrapper around docker commands.

Postman is the tool we recommend to be used when simulating the queries against the API, but feel free to use any other tool of your choice.

THE DOCKER STACK

We recommend the use of the included Docker stack to play with this Approov integration.

For details in how to use it, you need to follow the setup instructions in the Approov Shapes Demo Server walk-through, but feel free to use your local environment to play with this Approov integration.

THE POSTMAN COLLECTION

Import this Postman collection that contains all the API endpoints for the Approov Shapes Demo Server and we strongly recommend you to follow this demo walk-through after finishing the Approov integration that we are about to start.

The Approov tokens used in the headers of this Postman collection where generated by this helper script and they cover all necessary scenarios, but feel free to use the script to generate some more valid and invalid tokens, with different expiry times and custom payload claims. Some examples of using it can be found here.

INSTALL DEPENDENCIES

If not already using the NPM packages express-jwt and dotenv in your project, please add them:

npm install --save express-jwt dotenv debug

ORIGINAL SERVER

Let’s use the original-server.js as an example of a current server to which we want to add Approov to protect some or all the endpoints.

After we add only the necessary code to integrate Approov, the end result will look like we have now in the approov-protected-server.js.

 Learn More about Mobile API Security! 

HOW TO INTEGRATE

We will learn how to go from the original-server.js to the approov-protected-server.js and how to configure the server.

In order to be able to check the Approov token, the express-jwt library needs to know the secret used by the Approov cloud service to sign it. A secure way to do this is by passing it as an environment variable, as you can see we have done here.

Next we need to define two callbacks to be used during the Approov token check process. One callback is to perform the check itself with the library express-jwt and the other is to handle any errors occurred during that check.

Let’s breakdown the example implementation to make it easier to adapt to your current project.

Require Dependencies

We need to require the dependencies we installed before.

Configuration file:

Approov Protected Server file:

Setup Environment

If you don’t have already an .env file, then you need to create one in the root of your project by using this .env.example as your starting point.

The .env file must contain these two variables:

# the base64 encode is for value: approov-base64-encoded-secret
APPROOV_BASE64_SECRET=YXBwcm9vdi1iYXNlNjQtZW5jb2RlZC1zZWNyZXQ=
APPROOV_ABORT_REQUEST_ON_INVALID_TOKEN=true
APPROOV_ABORT_REQUEST_ON_INVALID_CUSTOM_PAYLOAD_CLAIM=true
APPROOV_LOGGING_ENABLED=true

Now we can read them from our code, as is done in the configuration file:

Customizable Approov Callbacks

These are callbacks used in the Approov Integration that you may want to customize to the needs of your application.

Let’s start with the logging callback that we can see in approov-protected-server.js:

Next we have the callback to get the claim value that we want to compare against the custom payload claim in the Approov token, as seen in approov-protected-server.js:

Each time an Approov token doesn’t validate for any reason, the Approov integration will pass the control to the application logic by invoking a callback such as the one defined in approov-protected-server.js:

The last customizable callback will be invoked by the Approov integration to allow the application to decide what action to take when the request claim value doesn’t match the custom payload claim value in the Approov token, as defined in approov-protected-server.js:

Approov Integration Core Callbacks

These core callbacks are specific to the Approov integration, and since they don’t interfere with the flow or behavior of your application, we think they are not in need of being customized.

Helper Functions

The core callbacks will need some very basic helper functions, like the ones defined in the approov-protected-server:

Approov Token

This callback will be used in the middleware to check the Approov token:

Then we need this callback to handle any error that may occur during the Approov token check:

Finally we want to handle when the Approov token succeeds in the validation process, as we have done approov-protected-server.js

Custom Payload Claim

We will use these two functions to validate if the claim value in the request matches the custom payload claim in the Approov token, as we can see in the approov-protected-server.js:

Middleware 

We will use the middleware approach to intercept all endpoints we want to protect with an Approov Token, so any interceptor must be placed before we declare the endpoints we want to protect, as is done in the approov-protected-server.js.

The following examples will use the callbacks we already have defined here to pass as the second parameter to the middleware interceptors.

For specific endpoints

To protect specific endpoints in a current server we only need to add the Approov interceptors for each endpoint we want to protect, as we have done here:

For all endpoints

To protect all endpoints we only need to declare the Approov interceptor for the API root endpoint /, thus we need to modify the above code to look like this:

Approov in Action

Let's see how to query the NodeJS Express API from Postman with the collection we told you to install in the requirements section.

NOTE:

For your convenience the Postman collection includes a token that only expires in the very distant future for this call "Approov Token with valid signature and expiry time". For the call "Expired Approov Token with valid signature" an expired token is also included.

 

Postman view with an Approov token correctly signed and not expired:

postman-shapes-valid-token

 

Postman view with token correctly signed but this time it is expired:

postman-shapes-expired-token

 

Shell view with the logs for the above requests: 

 shell-shapes-valid-and-expired-token-1

Request Overview:

We used a helper script to generate an Approov Token that was valid for 1 minute.

In Postman we performed 2 requests with the same token and the first one was successful, but the second request, performed 2 minutes later, failed with a 400 response because the token had already expired as we can see by the log messages in the shell view.

Play Time for the Approov Shapes Demo Server

If you have not done it already, now is the time to follow the Approov Shapes Demo Server walk-through to get a feel for how all this works.

The Approov Shapes Demo Server contains endpoints with and without the Approov protection. The protected endpoints differ in the sense that one uses the optional custom payload claim in the Approov token.

We will demonstrate how to call each API endpoint with screen-shots from Postman and from the shell. Postman is used here as an easy way to demonstrate how you can play with the Approov integration in the API server, but to see a real demo of how Approov would work in production, you need to request a demo here.

The Code Difference

If we compare the original-server.js with the approov-protected-server.js we will see this file difference:

As we can see the Approov integration in the current server is simple, easy and is done with just a few lines of code.

If you have not done it already, now is time to follow the Approov Shapes Demo Server walk-through to understand the flow.

PRODUCTION

In order to protect the communication between your mobile app and the API server is important to only communicate over a secure communication channel, also known as https.

Please bear in mind that https on its own is not enough, certificate pinning must be also used to pin the connection between the mobile app and the API server in order to prevent Man in the Middle Attacks.

We do not use https and certificate pinning in this Approov integration example because we want to be able to run the Approov Shapes Demo Server in localhost.

However in production it will be mandatory to implement at least static pinning or dynamic pinning.

Test Drive Approov!