简体   繁体   中英

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.

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 .

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:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM