Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 911
Ragnar Avatar asked Aug 09 '16 07:08

Ragnar


People also ask

Which is the secure way to communicate between client and server?

SSL is a security protocol that secures communication between entities (typically, clients and servers) over a network. SSL works by authenticating clients and servers using digital certificates and by encrypting/decrypting communication using unique keys that are associated with authenticated clients and servers.

Is NodeJS Express secure?

While Node. js itself has its own set of security vulnerabilities such as NPM phishing and regular expression Denial of Service attacks, the real threat actually lies in the jigsaw way your application gets built. For example, Express. js is often used to provide server-side logic.

Is Express session secure?

It contains only an encrypted ID that is used by the server to identify which session object corresponds with that user. Session data is then only available on the server itself which further insulates it from some types of attacks.


2 Answers

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.

like image 151
David Gatti Avatar answered Sep 28 '22 18:09

David Gatti


As I just finished the auth part of my AngularJS application. The answer will be JWT and Passport, you should use the great technologies to protect your data / API.

If you use the JWT library, it will help you hold the http heads for authorization.

Some of the code I used:

app.js

var jwt = require('express-jwt');

var auth = jwt({
    secret: config.jwt.secret,
    userProperty: 'payload'
});

app.use('/api/secret', auth, apiSecretRoutes);

login.js

module.exports.login = function (req, res) {
    if (!req.body.username || !req.body.password) {
        return tools.sendJSONresponse(res, 400, {
            message: 'All fields required!'
        });
    }

    passport.authenticate('local', function (err, user, info) {
        var token;
        if (err) {
            return tools.sendJSONresponse(res, 404, err);
        }

        if (user) {
            token = user.generateJwt();
            return tools.sendJSONresponse(res, 200, {
                ok: true,
                message: 'welcome ' + user.name,
                token: token
            });
        } else {
            return tools.sendJSONresponse(res, 400, info);
        }
    })(req, res);
};

user.js

userSchema.methods.generateJwt = function() {
    var expiryDays = 1;
    var expiry = new Date();
    expiry.setDate(expiry.getDate() + expiryDays);

    return jwt.sign({
        _id: this._id,
        username: this.username,
        name: this.name,
        exp: parseInt(expiry.getTime() / 1000)
    }, config.jwt.secret);
};

More Refs:

  • https://thinkster.io/angularjs-jwt-auth
  • http://devdactic.com/restful-api-user-authentication-1/
  • http://devdactic.com/restful-api-user-authentication-2/
  • http://jwt.io
  • https://github.com/auth0/express-jwt
like image 38
Yishi Guo Avatar answered Sep 28 '22 17:09

Yishi Guo