Express Validator Tutorial

  • 2019-03-06 02:42 AM
  • 67

Learn how to use Express Validator, a set of middleware functions, to perform server-side validation on user data.

TL;DR: In this article you will learn to validate and sanitize data in your Express.js applications using a set of middleware called express-validator. You will do so by completing a demo application that takes in user input and validates/sanitizes it using this library. If you want to see the complete application developed throughout this article, take a look at this GitHub repository.

Prerequisites

Software you need to install to follow this tutorial:

What Is Express Validator?

According to the official website, Express Validator is a set of Express.js middleware that wraps validator.js, a library that provides validator and sanitizer functions. Simply said, Express Validator is an Express middleware library that you can incorporate in your apps for server-side data validation.

Why Server-Side Validation?

Mainly speaking, you must care about server-side validation because data coming from other clients (single-page apps, regular web apps, mobile applications, etc.) cannot be trusted. For example, your servers have no means to know if a malicious user (or virus) disabled front-end validation (e.g., JavaScript) to allow the app to submit bogus data to your server. That is, client-side validation is not enough.

Set Up Your Playground For Express Validator

To start playing with Express Validator, you will clone a simple Express server to use as a playground. To do so, open your terminal in a preferred directory and clone the starter project with the following command:

# clone repository
git clone https://github.com/auth0-blog/expressjs-validator.git

# move into your clone repository
cd expressjs-validator

Then, install all the project dependencies by running the following command in the project root:

npm install

This simple Express application contains just enough for you to get started and focus on learning about the express-validator library. For example, if you check the views/layout.pug file, you will see that it contains some basic HTML elements to define how the app should look like.

Note: If you are not familiar with Pug, the template engine, you might find the syntax of this file a bit different. Don’t worry, you don’t need to be acquainted with Pug to follow this article along. Also, if you take a close look to the source code, you will probably understand what is going on. For example, you will see a line starting with link that contains the href keyword pointing to a BootStrap file. This is just the code telling the browser to import an external CSS file, quite similar to what you would do in HTML.

Besides the views/layout.pug file, these are other important files that you must know about:

  • ./routes/index.js: This file is responsible for rendering the homepage of your app. The res.render('index') line will make Express and Pug work together to render the views/index.pug file.
  • ./routes/users.js: For now, this file adds an endpoint to your app that doesn’t do anything. Soon, you will start using this file to learn about the express-validator library.
  • ./public/javascripts/script.js: This is the file that will be in charge of sending user data to your backend. The requests will be some AJAX calls to the endpoint defined on the routes/users.js file.
  • ./app.js: This is the file responsible for bootstrapping the backend. This file sets up Pug as the template engine and tells Express.js where to find the other JavaScript files.

With that, you now know how the app is structured, but don’t run the project yet! You still need to define the home page of your app.

Build Homepage For User Input

After learning about the structure of the playground, you will need to add the following code to the views/index.pug file:

extends layout

block content
  .container
    .alert(class="alert-danger", role="alert", id="error-group", style="display: none")
      ul(id="errors")
    .row
      .col-sm.col-md-8.offset-md-2.col-lg-6.offset-lg-3
        h3 Welcome To Express Validator!
        form
          .form-group
            input.form-control(type="text", id="name", placeholder="Name")
          .form-group
            input.form-control(type="text", id="classYear", placeholder="Class Year")
          .form-group
            input.form-control(type="text", id="weekday", placeholder="Available Weekday")
          .form-group
            input.form-control(type="email", id="email", placeholder="Email")
          .form-group
            input.form-control(type="password", id="password", placeholder="Password")
          .form-group
            input.form-control(type="password", id="confirmPassword", placeholder="Confirm Password")
          .form-group
            button.form-control(type="button", class="btn btn-primary", id="signup-btn") Submit

What you are doing here is to add a bunch of input elements to the homepage that will receive user input to be sent to the backend. With that covered, you have everything in place to have a sneak peek at the app. Go to the project root directory and run the following command to get the app started.

node app.js

Now, if you visit http://localhost:3000/ in your favorite browser, you should see the following page:

Express Validator Tutorial: Scaffolding the sample app.

Note: You can stop the server now, but whenever you add a new feature/functionality, you will need to restart the server if it is already running or just start it.

Once the user enters data on your homepage and clicks the Submit button, you will need to handle the on submit event and make an AJAX request to your Express back-end. To do that, add the following code to your ./public/javascripts/script.js file:

$('#signup-btn').click(function () {
  $.ajax({
    url: '/users',
    type: 'POST',
    cache: false,
    data: {
      name: $('#name').val(),
      classYear: $('#classYear').val(),
      weekday: $('#weekday').val(),
      email: $('#email').val(),
      phoneNumber: $('#phoneNumber').val(),
      password: $('#password').val(),
      confirmPassword: $('#confirmPassword').val()
    },
    success: function () {
      $('#error-group').css('display', 'none');
      alert('Your submission was successful');
    },
    error: function (data) {
      $('#error-group').css('display', 'block');
      var errors = JSON.parse(data.responseText);
      var errorsContainer = $('#errors');
      errorsContainer.innerHTML = '';
      var errorsList = '';

      for (var i = 0; i < errors.length; i++) {
        errorsList += '<li>' + errors[i].msg + '</li>';
      }
      errorsContainer.html(errorsList);
    }
  });
});

From the code above, on form submission, a POST request is made to the http://localhost:3000/users endpoint with the data entered by users on the HTML fields defined before. If there is an error during validation, this code will make sure to display the error messages inside a div marked with the alert class. If no errors are found, a successful validation will trigger an alert with this message: “Your submission was successful”.

Server-Side Validation With Express Validator

Now that you have your front-end set up, you will start learning about express-validator. To do that, the first thing you will need to do is to install the library:

npm install express-validator --save

After installing express-validator, open the routes/users.js file and import the check API to use its validation functions:

// ... call to require('express') ...
const {check, validationResult} = require('express-validator/check');

// ... leave the rest untouched ...

Making sure fields are not empty

Now, to validate your form input, you need to pass an array in which you specify the fields that you want to validate as a second argument to your route handler for /users POST requests. To do that, add the following code after the GET route handling code in routes/user.js:

// ... require statements ...

// ... router.get ...

router.post('/', [
    check('name').not().isEmpty().withMessage('Name must have more than 5 characters'),
    check('classYear', 'Class Year should be a number').not().isEmpty(),
    check('weekday', 'Choose a weekday').optional(),
    check('email', 'Your email is not valid').not().isEmpty(),
    check('password', 'Your password must be at least 5 characters').not().isEmpty(),
  ],
  function (req, res) {
    const errors = validationResult(req);
    console.log(req.body);

    if (!errors.isEmpty()) {
      return res.status(422).jsonp(errors.array());
    } else {
      res.send({});
    }
  });

module.exports = router;

The string passed as an argument to the check function specifies which data field you want to validate (e.g., classYear). The not().isEmpty() function chain makes the library validate that this field is not empty. The string argument added to withMessage() specifies a custom error message which will be send back to your users if this particular field violates a validation requirement.

Note: You can also provide a custom error message by passing it as a second argument to the check() function.

By calling the optional() function on it, you have made the weekday field optional. So far, you have only specified how you want your fields to be validated. You might be wondering where Express.js actually does the validation. Validation happens in the request handler when it calls the validationResult() function. To test this, run your application and submit an empty form to the server and you should see the following error displayed in red.

Express validator showing error messages.

Remark how there is no error for the weekday field, this is because you made the field optional during validation. Pretty cool, huh?

Validating fields’ length

You can also check if a data field meets a certain character length requirement by using the isLength() function. This function takes in an object in which you specify the minimum and/or the maximum number of characters in that field. To see this in action, update the validation requirements for the name and password field as follows:

[
  // ... leave other validations untouched ...
  check('name').not().isEmpty().isLength({min: 5}).withMessage('Name must have more than 5 characters'),
  check('password', 'Your password must be at least 5 characters').not().isEmpty().isLength({min: 5}),
]

Now, restart the app and try to enter a name and password less than five characters long. You should see the app complaining about the field length.

Validating fields’ type

Apart from validating the character length of a field, you can also validate its type or validate it against a list. For example, you can specify that your classYear field needs to be an integer. You can also specify that weekday should not be Saturday or Sunday. To do that, update your validation requirements as follows:

[
  // ... leave other validations untouched ...
  check('classYear', 'Class Year should be a number').not().isEmpty().isInt(),
  check('weekday', 'Choose a weekday').optional().not().isIn(['Sunday', 'Saturday']),
]

Now, after restarting the app, if you try to enter a value which is not an integer in the class year field, you will see an error message. Also, if you enter “Saturday” or “Sunday” in the weekday field, you will see the backend complaining.

Validating and sanitizing emails

Express Validator also validates emails with the isEmail() function. Besides that, you can also make this library normalize emails with the normalizeEmail() function. In case you are wondering what it means to normalize an email, you can read about it in this Stack Overflow post.

In order to validate the email field, refactor the check('email' call in your code:

[
  // ... leave other validations untouched ...
  check('email', 'Your email is not valid').not().isEmpty().isEmail().normalizeEmail(),
]

Then, after restarting the app, if you enter an invalid email on your homepage you will get an error message:

Validating email addresses with Express Validator

Sanitizing fields with trim and escape

With Express Validator, you can also trim away spaces from your data and escape special characters using the trim() and escape() functions. The escape() function can really come in handy when protecting yourself from cross-site scripting attacks. To add this feature to your app, refactor the call to check('name') as follows:

[
  // ... leave other validations untouched ...

  check('name').exists().isLength({min: 5}).trim().escape().withMessage('Name must have more than 5 characters'),
]

To test this, the starter project came with code that prints every request body to the console after validation. So, imagine a malicious user types the following JavaScript code in your name field: <script> alert("hello, there");</script>. By using escape you will have no problem, as the name that you will get in your backend will look like:

&lt;script&gt; alert(&quot;hello, there&quot;);&lt;&#x2F;script&gt;

That is, Express Validator transformed the malicious code into special HTML characters. Amazing, right?

Validating with custom validators

Although Express Validator offers a bunch of solutions out of the box for you, chances are you will need to implement some custom validation. For example, imagine you need to make sure that the password field matches the confirmPassword field. To do that, you can use the custom() validation function as follows:

[
  // ... leave other validations untouched ...

  check('confirmPassword', 'Passwords do not match').custom((value, {req}) => (value === req.body.password)),
]

The custom function takes in a function (an arrow function in this case) as an argument and checks if the value of the confirmPassword is the same as the value of the req.body.password field. To see this in action, restart your app, then enter a different password and you should get the message saying that “passwords do not match”.

Conclusion

In this article, you learned how to use the Express Validator middleware to validate and sanitize user data in an Express application. Guess what? You only scratched the surface of what is possible with Express Validator. Aside from learning more validation and sanitization functions, you can learn how to add wildcards to your validations, do schema validation and whole body validation from Express Validator’s documentation. I will love to see what you build with Express Validator.

Learn More

Node.js - Express Persistent Session Store with PostgreSQL + Sequelize
Secure Node.js, Express.js and PostgreSQL API using Passport.js
Fullstack Vue App with Node, Express and MongoDB
MEAN Stack Tutorial MongoDB, ExpressJS, AngularJS and NodeJS
Moving from NodeJS to Go

Originally published by Vladimir Fomene at https://auth0.com

Suggest