Ragnar Ragnar - 3 months ago 19
Node.js Question

Node/Express - Good approach to secure communication between client/server

I'm building a backend API with Node/Express, which get the data from a MongoDB. The front will be written in React.

I would like to secure the communication client/server, but I don't know how I have to think about the process.

I see many tutorial about

passport
or
JWT
, but this is good for an user authentication.

I don't know if creating a token for every request based on the time (for example) is a good approach or it's too consuming for a web app.

But my goal is to secure the data because even if the API is private you can easily find out the route and try to figure it out how to fake request with Postman or something else to scrap the data.

Answer

The accepted standard is to use a fixed API KEY. This peace of info should be a randomly generated string that you send in each request in the header. Your server has to check the HTTP request each time to see if the API KEY is present in the header, and if it is, then it has to check against the stored value in the environment variable (never store the API KEY in code).

If the API KEY gets compromised, then you can easily update the env variable, and you are good again.

Now, this solution will be pointless without a HTTPS connection, because anyone will be able to sniff the traffic and see the API KEY. An encrypted connection is a must in this case.

This approach is used by virtually every company that has a public API: Twitter, Facebook, Twilio, Google etc.

Google for example has an extra step where they give you a token that will expire, but this will be an over kill in your case: at least in the beginning.

The following code is an example of my implementation of a API KEY check

app.use(function(req, res, next) {

    //
    //  1. Check if the APIKey is present
    //
    if(!req.headers.authorization)
    {
        return res.status(400).json(
            {
                message: "Missing APIKey.",
                description: "Unable to find the APIKey"
            }
        );
    }

    //
    //  2. Remove Basic from the beginning of the string
    //
    let noBasic = req.headers.authorization.replace('Basic ', '');

    //
    //  3. Convert from base64 to string
    //
    let b64toString = new Buffer(noBasic, 'base64').toString("utf8");

    //
    //  4. Remove the colon from the end of the string
    //
    let userAPIKey = b64toString.replace(':', '');

    //
    //  5. Check if the APIKey matches the one on the server side.
    //
    if(userAPIKey != process.env.API_KEY)
    {
        return res.status(400).json(
            {
                message: "APIKey don't match",
                description: "Make sure what you are sending is what is in your server."
            }
        );
    }

    //
    //  -> Go to the next stage
    //
    next()

});

You can check the whole file with the whole implementation hear.

Comments