Securing your admin section

Now, it’s time to secure the admin section so that only authorized users can log in.

An important thing to note here is that we will need to secure both the client-side admin section and also our server-side APIs, because it is relatively easy to bypass client-side validations.

We will start with securing our server-side code. ExpressJS comes with its own session management and encryption modules.

We will enable cookieParser in our app by adding the following line to our angcms/app.js file:

app.use(express.cookieParser('secret'));

Using bcrypt to encrypt passwords

To encrypt confidential data such as passwords, we will use a popular utility called bcrypt to hash the password before it is stored in the database.

Let’s download and install the bcrypt-nodejs package using the following terminal command from the root of the project folder:

npm install bcrypt-nodejs

Next, we will include this in our ExpressJS app. As we will be securing our routes, we’ll include the bcrypt module in our angcms/routes/api.js file as follows:

var bcrypt = require('bcrypt-nodejs');

Adding a new admin user

Along with this, we will create our route to add in a new admin user as follows:

router.post('/add-user', function(request, response) {
    var salt, hash, password;
    password = request.body.password;
    salt = bcrypt.genSaltSync(10);
    hash = bcrypt.hashSync(password, salt);

    var AdminUser = new adminUser({
        username: request.body.username,
        password: hash
    });
    AdminUser.save(function(err) {
        if (!err) {
            return response.send('Admin User successfully created');

        } else {
            return response.send(err);
        }
    });
});

Here, we first start by defining our password, salt, and hash variables.

Then, using bcrypt and salt, we generate the hash string of the password.

Note

Using the salt variable is optional with bcrypt, but it is recommended, as it makes it difficult for potential hackers to decrypt the hashed password.

We then create a new instance of the AdminUser object, store the username and hashed password, and run the save method to save this information in the AdminUser document in MongoDB.

Creating the route for authenticating login

Next, we create the route for login. Add the following code to the api.js file:

router.post('/login', function(request, response) {
  var username = request.body.username;
  var password = request.body.password;

  adminUser.findOne({
    username: username
  }, function(err, data) {
    if (err | data === null) {
      return response.send(401, "User Doesn't exist");
    } else {
      var usr = data;

      if (username == usr.username && bcrypt.compareSync(password, usr.password)) {

        request.session.regenerate(function() {
          request.session.user = username;
          return response.send(username);

        });
      } else {
        return response.send(401, "Bad Username or Password");
      }
    }
  });
});

The code piece, although long, is fairly straightforward.

We capture the username and password as variables from the post data. We then check to see if the username is present, and if it is, then using the compare method of bcrypt, we check to see if the password entered matches that stored in the database.

Once the username and password match, we create the user session and redirect the user to the page’s listing page.

In case the username or password doesn’t exist, we return back with a status code 401 and a relevant error message.

We will be using this status code in our angularjs side to redirect the users in case of session time outs and so on.

Creating the logout route

After the login function, we create the logout function as follows:

router.get('/logout', function(request, response) {
    request.session.destroy(function() {
        return response.send(401, 'User logged out');

    });
});

The function will simply destroy the session.