In this multi-part tutorial, we will be creating a simple Phaser 3 game that has authentication and a leaderboard. For our game, we are going to create a user sign up / login flow using Node.js, Express, and MongoDB. After the player has logged into our game, they will be able to view the leaderboard and submit new high scores to the database. Lastly, our server will also be responsible for hosting our Phaser game.

The goal of this tutorial is to teach you the basics of adding user authentication to your game and how to create a leaderboard. You will learn how to:

Create a simple server using Node.js and Express

Setup user authentication using MongoDB, Passport, and JWTs

Protect server routes using authentication middleware

Create a leaderboard using data from an API

Allow the user to reset their password

You can download all of the files associated with the source code for Part 1 here .

Don't miss out! Offer ends in Access all 200+ courses

Access all 200+ courses New courses added monthly

New courses added monthly Cancel anytime

Cancel anytime Certificates of completion ACCESS NOW

Tutorial Requirements

For this tutorial, we will be using Node.js and npm to install the required packages that are needed for this project. In order to follow along with this tutorial, you will need to have Node.js and NPM installed locally, or you will need access to an environment that already has them installed. We will also be using the Command Prompt (Windows) / Terminal (Mac) to install the required packages, and to start/stop our Node server.

Having prior experience with these tools is a plus, but it is not required for this tutorial. We will not be covering how to install these tools as the focus of this tutorial is making a leaderboard with Phaser. The last thing you will need is an IDE or Text Editor for editing your code.

To install Node.js, click the link here: and choose the LTS version. You can download and use the current version with this tutorial, however, the LTS version is recommended for most users. When you install Node.js, NPM will also be installed on your computer. Once you have these tools installed, you can move on to the next part.

Also, at the time this tutorial was created, the latest LTS version of Node.js was v10.13.0 . You can check your version of Node by running node -v from the terminal. It is recommended you be on this or a new version when following along.

Lastly, for this tutorial, we will be using MongoDB Atlas for our database. You are welcome to use a local version of it, or another cloud solution for your database, but that is outside the scope of this tutorial.

Let’s get started!

MongoDB Atlas

For our database, we will be using MongoDB and for this tutorial, we will be using its Atlas cloud service to host our database. It offers a free 512 MB storage cluster for all users that create an account, and it does not require any billing information to make your account.

For the next part of this tutorial, we will be walking you through setting up an account and showing you how to get the connection information for your database. If you would like to use another service, or if you have MongoDB installed locally, you can skip the rest of this section and move on to the next.

To create an account and a free cluster, visit this URL here: MongoDB Atlas and fill out the signup form. Once you have filled out all of the details, click on the Get Started Free button. You will be taken to a screen where you can set up your free cluster.

For this tutorial, we will be using the default settings for the AWS free tier. Click on the green create cluster button to have MongoDB Altas start provisioning your cluster.

It will take a few minutes for your cluster to be fully provisioned and ready. Once your cluster is available, we need to configure a few things before we connect to our new database. First, we are going to setup which IPs are whitelisted to connect to our cluster. By default, anyone will be able to connect to the cluster if they have the correct username and password for the database. By adding your IP address to the whitelist, it will help make your cluster more secure.

To add your IP, click on the Security tab and then click on the IP Whitelist tab.

Next, click on the green Add IP Address button, and in the modal that appears click on the Add Current IP Address button, or enter your IP address into the text field.

Lastly, click on the Confirm button to save your changes. It will take a minute or two for the settings to become active. Once this setting is enabled, we will create a database user. To create a database user, on the Security tab click on the MongoDB Users tab.

Next, click on the Add New User button, and in the modal that appears enter a name for your database user and enter a password, or click on the Autogenerate secure password button to have it populate a secure password.

For the rest of the settings, leave the default options selected and then click on the Add User button to create your user. Once these changes are deployed to your cluster, you will be able to connect to your new database. To connect to your database, you will need to get the URI connection string for your cluster.

To do this, click on the Overview tab and then click on the connect button. In the modal that appears, click on the Connect Your Application button, and then click on the Short SRV connection string button.

This will show you the URI connection string for your cluster with the password part set to <PASSWORD> . You will need to update this part of the string with the password you created earlier for your database user.

Creating Our Server

Now that we have created our MongoDB cluster, and we have the information needed to connect to it, we will start building out the API for allowing users to signup for our game. To get started, create a new folder on your computer, it can be called anything you want. This folder will be our new project folder, and it will contain all of the code for our game.

The first thing we will add to the project folder is an environment file, which we will use to store the sensitive data for our project. In the folder you made, create a new file called .env and in this file add the following code and replace placeholder with the MongoDB URI connection string that we just retrieved from MongoDB Atlas:

MONGO_CONNECTION_URL=placeholder 1 MONGO_CONNECTION_URL = placeholder

By placing these details into a .env file, we can use an npm package called dotenv to load in these credentials while working locally, that way these credentials are not hardcoded in our code files.

Notes:

You can also pass in these values through the terminal when you run your server code, but for the purpose of this tutorial, we will be loading them in through the .env file.

file. In case you will be using a version control system with your project code (like git), it is a best practice to make sure this file does not get committed with your source code and it is usually best to add the .env file to the file ignore list ( .gitignore if using git). For this tutorial, we will not be using a version control system.

Next, since we will be using external dependencies in our project we will need to create a package.json file to keep track of these dependencies. To do this, open a terminal/command prompt window and navigate to your project folder. Once there, run the following command:

npm init -f 1 npm init - f

These will create a package.json file with some default values. For now, we will leave these values alone.

Now, we will install some of the dependencies will we need for our project. In the terminal, run the following command:

npm install --save express body-parser dotenv 1 npm install -- save express body - parser dotenv

This will install the express , body-parser , and dotenv packages into our project, and by passing the save flag to the npm install command it will automatically add those packages to our package.json . The express package is a web application framework for Nodejs that makes it easy to create a web server to host your APIs and static files. The body-parser package is a middleware package that will parse the request body that is sent to our express server.

With the required dependencies installed, we can create our server. To do this, create a new file called app.js and add the following code to that file:

// reads in our .env file and makes those values available as environment variables require('dotenv').config(); const express = require('express'); const bodyParser = require('body-parser'); // create an instance of an express app const app = express(); // update express settings app.use(bodyParser.urlencoded({ extended: false })); // parse application/x-www-form-urlencoded app.use(bodyParser.json()); // parse application/json // main routes app.get('/status', (req, res, next) => { res.status(200); res.json({ 'status': 'ok' }); }); // catch all other routes app.use((req, res, next) => { res.status(404); res.json({ message: '404 - Not Found' }); }); // handle errors app.use((err, req, res, next) => { res.status(err.status || 500); res.json({ error : err }); }); // have the server start listening on the provided port app.listen(process.env.PORT || 3000, () => { console.log(`Server started on port ${process.env.PORT || 3000}`); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // reads in our .env file and makes those values available as environment variables require ( 'dotenv' ) . config ( ) ; const express = require ( 'express' ) ; const bodyParser = require ( 'body-parser' ) ; // create an instance of an express app const app = express ( ) ; // update express settings app . use ( bodyParser . urlencoded ( { extended : false } ) ) ; // parse application/x-www-form-urlencoded app . use ( bodyParser . json ( ) ) ; // parse application/json // main routes app . get ( '/status' , ( req , res , next ) = > { res . status ( 200 ) ; res . json ( { 'status' : 'ok' } ) ; } ) ; // catch all other routes app . use ( ( req , res , next ) = > { res . status ( 404 ) ; res . json ( { message : '404 - Not Found' } ) ; } ) ; // handle errors app . use ( ( err , req , res , next ) = > { res . status ( err . status | | 500 ) ; res . json ( { error : err } ) ; } ) ; // have the server start listening on the provided port app . listen ( process . env . PORT | | 3000 , ( ) = > { console . log ( ` Server started on port $ { process . env . PORT | | 3000 } ` ) ; } ) ;

In the code above, we did the following:

We required dotenv , which will read in our .env file and make those values available as environment variables. It is recommended that you call this method as early as you can in your app.

, which will read in our file and make those values available as environment variables. It is recommended that you call this method as early as you can in your app. Next, we loaded in the rest of the modules that we will need for our app.

We then created our express app instance, and we told the app to use the bodyParser module we loaded. By telling the app to use the bodyParser module, it will allow us to parse incoming POST body payloads.

module we loaded. By telling the app to use the module, it will allow us to parse incoming POST body payloads. Next, we created a GET /status endpoint for our server to listen on and when this endpoint is called the server will return a 200 response. To create a route, we first need to tell express which HTTP method is supported for this route and we do this by calling the appropriate method on app , for example, get or post . Then, in the method call, we pass two arguments, the first is the route that we want to make available, /status in this example, and the second argument is the callback function that will be invoked when a call is made to this route. This callback function will receive three arguments when it is called: req – The request object which will contain all of the metadata for the request. Some of this data includes headers, body, query string parameters, etc. res – The response object that is returned to the caller. This object allows us to set the status code, the type of response, and the payload that is returned. next – Can be used to call the next middleware in the chain if we are not done processing the request.

endpoint for our server to listen on and when this endpoint is called the server will return a 200 response. We then created two middleware handlers for our express app: an error handler and a 404 handler. The error handler middleware is unique because this middleware will receive four arguments instead of three, and this new argument is the error that was sent. The 404 handler middleware will be invoked last if no other middleware has returned a response. The middleware acts as a catch-all if the user tries to call any routes we have not explicitly defined.

Finally, we told our server to start listening on port 3000, or if a PORT environment variable is set the app will use that one.

To test our application, run the following command in the terminal:

node app.js 1 node app . js

You should see a message about the server starting on port 3000.

If you visit http://localhost:3000/status in your browser, you should see the status message we created.

Lastly, if you visit any other route, for example, http://localhost:3000/status2, you should see the 404 message about the route not being found.

Creating a router

Now that we have the express server up and running, we are going to move the status route to a new file. By doing this, it will help keep our code organized and make it easier to maintain as our project grows. To do this, create a new folder at the root of your project called routes . Then, in the routes folder create a new file called main.js and add the following code to that file:

const express = require('express'); const router = express.Router(); router.get('/status', (req, res, next) => { res.status(200); res.json({ 'status': 'ok' }); }); module.exports = router; 1 2 3 4 5 6 7 8 9 10 const express = require ( 'express' ) ; const router = express . Router ( ) ; router . get ( '/status' , ( req , res , next ) = > { res . status ( 200 ) ; res . json ( { 'status' : 'ok' } ) ; } ) ; module . exports = router ;

In the code above, we created a new express.Router , which is a complete middleware and routing system that acts like a mini express app that we can import into our main app. So, by adding the /status endpoint to this router, we can remove that logic from the app.js file, and instead reference the new router.

To do this, open app.js and add the following code at the top of the file with the other imports:

const routes = require('./routes/main'); 1 const routes = require ( './routes/main' ) ;

Then, replace the following code:

app.get('/status', (req, res, next) => { res.status(200); res.json({ 'status': 'ok' }); }); 1 2 3 4 app . get ( '/status' , ( req , res , next ) = > { res . status ( 200 ) ; res . json ( { 'status' : 'ok' } ) ; } ) ;

with this:

app.use('/', routes); 1 app . use ( '/' , routes ) ;

Now, if you save your code changes, stop the server, and restart it, you should still be able to navigate to the /status endpoint.

Conclusion

With the new router in place, that brings part one of this tutorial to an end. In Part 2, we will do the following:

Add user authentication routes to our API that will allow someone to log in and signup.

Add the logic for connecting to MongoDB.

Add logic to secure our API endpoints.

I hope you enjoyed this and found it helpful! If you have any questions, or suggestions on what we should cover next, please let us know in the comments below.