Firebase Functions Tutorial — Data Validation

Image for post
Image for post
Image by Mohamed Hassan from Pixabay

A few months ago, I published an article (and video) covering how to build a REST API using Firebase Functions. Since then, I’ve gotten a lot of questions on how to implement more features such as authentication and data validation. In my last article, I covered authentication and in this article, we’re going to be talking about data validation.

When creating a REST API, authentication and data validation are critical to maintaining the integrity of your data. Authentication prohibits malicious people 😠 from sniffing API endpoints and manipulating or accessing data. Data validation prohibits authenticated and front end developers from sending malformed data to the backend/database.

Since this tutorial is going to build on a previous one, we’ll be using the code from it. If you’d like to follow along you can find it in this BitBucket Repo. So, clone the project and let's start coding 🙌!

Firebase Setup

In order to publish our functions, add users to our database, and use authentication, we’re going to have to set up a Firebase project. So, head over to https://firebase.google.com/ create an account and then click “Go to console”. Next, click on the “Add project” button and name it whatever you’d like. Click through the other options choosing the defaults.

Firestore

Next click on “Cloud Firestore” in the left-hand menu.

Image for post
Image for post
Cloud Firestore

Then, at the top of the screen click “Create database”.

Image for post
Image for post
Firestore Database Creation

For now, choose Start in test mode and pick the default server location.

Image for post
Image for post
Firestore Test Mode

Warning: This will leave your database open for anyone to read and write to it. If you are going to use this in a production setting, PLEASE familiarize yourself with Firestore rules.

Firebase CLI

Firebase makes it pretty simple to install their boilerplate functions in our project. In my previous article, we signed up for Firebase and added the config to our project, but for functions, we’ll need to install the Firebase CLI globally on our computer. To do this, open your terminal and run the following command:

npm install -g firebase-tools

Now that we have it installed, we need to sync it to our account. Run the following in your command prompt and log in:

firebase login

Initializing Firebase in Cloned Project

To sync the cloned project (from the beginning) with your Firebase account, we’re going to need to delete some files. Go ahead and delete the following files out of the project:

  1. .firebaserc
  2. firebase.json
  3. firestore.rules
  4. firestore.indexes.json

Now, open a terminal at the root of the Firebase API project cloned in the beginning. Then run the following command:

firebase init

Provide these answers to the following questions:

  • Are you ready to proceed? — Y
  • Which Firebase CLI features do you want to set up for this folder? — Functions
  • Please select an option: — Use an existing project
  • Select the firebase project you set up earlier
  • What language would you like to use to write Cloud Functions? — JavaScript
  • Do you want to use ESLint to catch probable bugs and enforce style? — y
  • File functions/package.json already exists. Overwrite? — n
  • File functions/.eslintrc.json already exists. Overwrite? — n
  • File functions/index.js already exists. Overwrite? — n
  • File functions/.gitignore already exists. Overwrite? — n
  • Do you want to install dependencies with npm now? — Y

Next, to make sure all previous dependencies are installed cd into the functions folder from the terminal and run the following command:

npm i 

Firebase Functions Data Validation

Since our Firebase Functions utilize the Express Framework, we can tap into a large ecosystem of plugins. In particular, we’ll be using the express-validator. This makes it extremely easy to write validations for our endpoint.

To install express-validator, open a terminal in of the functions folder of the project, and run the following command:

npm install --save express-validator

Since we only have one POST endpoint in our project, we’ll be focusing on that. You can see the code for it here:

app.post("/", async (req, res) => {
const user = req.body;
await admin.firestore().collection("users").add(user);
res.status(201).send();
});

What we want to do is pass in a request body with the following properties and validations:

  1. email— Required and verify its a valid email
  2. firstName — Required
  3. lastName — Required
  4. age — Required and must be an integer
  5. password — Required and Min Length of 6 characters
  6. userType — Must be either “admin” or “customer”
  7. language — Optional, but if added must be either “javascript”, “python”, or “C#”

Now we can start coding out our validator. At the top of our index.js file, import what we’ll need for express-validator.

const { body, validationResult } = require('express-validator');

The best aspect of express-validator is all of the built-in validators. We’ll use the body property we imported earlier to chain validators. Then we’ll place them in an array to use on as middleware on our endpoint:

const userCreationValidators = [
body('email').isEmail(),
body('firstName').notEmpty(),
body('lastName').notEmpty(),
body('age').isInt(),
body('password').isLength({min: 5}),
body('userType').notEmpty().isIn(["admin", "customer"]),
body('language').optional().isIn(['javascript', "python", "C#"])
];

Now we just need to add our validations to our endpoint and use the validationResult method to verify our request body verse our validations:

app.post("/", userCreationValidators, async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}


const user = req.body;
await admin.firestore().collection("users").add(user);

res.status(201).send();
});

Testing

So now if I run the Firebase local emulator to test my function locally and hit the endpoint with Postman without a request body, we’ll see we get a status of 400 and a response body with all the errors. The major benefit of the errors is that it will help our front-end developers adjust their requests.

Image for post
Image for post
Firebase Function Data Validation

Custom Error Messages

As we can see from the error messages, “Invalid value” is not very descriptive. This can particularly cause issues when you work on a team with dedicated front and backend developers. Luckily express-validator gives us an extremely easy way to add custom error messages.

All you have to do is chain the withMessage method after your validator:

const userCreationValidators = [
body('email').isEmail().withMessage("Email is invalid!")
body('firstName').notEmpty().withMessage("First Name required!"),
body('lastName').notEmpty().withMessage("Last Name required!"),
body('age').isInt().withMessage("Age must be int!"),
body('password').isLength({min: 5}),
body('userType').notEmpty().isIn(["admin", "customer"]),
body('language').optional().isIn(['javascript', "python", "C#"])
];

Video Tutorial

Firebase Functions — Data Validation Video Tutorial

Conclusion

As you can see data validation with Firebase Functions/Express is extremely easy with express-validator. This will ensure that your data integrity is protected and no malicious data will be injected into your database. I hope you found this tutorial helpful. If so, drop me line below. And, until next time, Happy Coding!

Written by

Full-stack developer developer for 7+ years with a passion for learning new things and sharing. For more, check out diligentdev.com.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store