Skip to main content

Developing Authentication System (in the Server)

This is a part 2 of our development blog series on "Masters of Mischief" which is our 3D Multiplayer game. In this post, we'll discuss the process and see a few code blocks about implementing an authentication system in the server.

Fig 1. Thunder Client snapshot | API testing

With our requirements set, let's move the card in our Trello board and go through the journey of making the work in progress.

Trello Card

First off, we'll use hashing in the project to encrypt and decrypt credentials. To use `bcrypt`, we will start by importing it in the `app.js`file.

🟢 app.js 🟨 Javascript 🟦 Node.js
import bcrypt from 'bcrypt';
import express from 'express';
import pool from './database.js';

const app = express();
const port = process.env.PORT || 8080;

Registration route:

Our /register endpoint will:

➣ Be a POST endpoint.

➣ Receive username and password in request body.

➣ Check if the username already exists in the system.

➣ Hash the plain password and register non-existing user into the database.

The codeblock below shows the code for registration endpoint.

🟢 Registration 🟨 Javascript 🟦 Express
app.post('/register', async(req, res) = >{
  try {
    const {
      username,
      password
    } = req.body;
    const connection = await pool.getConnection();
    const[rows] = await connection.query('SELECT * FROM players WHERE username = ?', [username]);
    if (rows.length == 0) {
      const hashedPassword = await bcrypt.hash(password, 10);
      const[rows] = await connection.query('INSERT INTO players(username, password) VALUES (?, ?);', [username, hashedPassword]);
      if (rows != null) {
        res.json("New user registered!");
      }
    } else {
      res.status(409).json("Username already exists")
    }
    connection.release();
  } catch(error) {
    console.error('Error executing query:', error);
    res.status(500).json({
      error: 'Database error'
    });
  }
})

Here, we used prepared statements to query the database that adds extra security and prevents from sql injection attacks. Also, we hash the password with a sweet cost factor of 10. Higher cost factor is an added security, however, it's performance heavy. Other code is self explanatory.

Login/Authentication route:

Our /authenticate endpoint will:

➣ Be a POST endpoint.

➣ Receive username and password in request body.

➣ Check if the username exists in the system.

➣ Compare the input password with the password of the existing username.

➣ Respond with the authenticated user data.

🟢 Auhentication 🟨 Javascript 🟦 Express
app.post('/authenticate', async(req, res) = >{
  try {
    const {
      username,
      password
    } = req.body;
    const connection = await pool.getConnection();
    const[rows] = await connection.query('SELECT * FROM players WHERE username = ?', [username]);
    if (rows.length > 0) {
      const isPasswordCorrect = await bcrypt.compare(password, rows[0].password);
      if (isPasswordCorrect) {
        res.status(200).json(rows[0]);
      } else {
        res.status(404).json("Username or Password Incorrect")
      }
    } else {
      res.status(404).json("Username or Password Incorrect")
    }
    connection.release();
  } catch(error) {
    console.error('Error executing query:', error);
    res.status(500).json({
      error: 'Database error'
    });
  }
})

Later from Unity3D, we call this endpoint to authenticate a user, and upon successful authentication, we can use the response user data to manage session.

We have used Thunder Client to test the API endpoints locally for a local server, and here is a playback of the testing.

GIF playback of full API testing
Fig 2. API Testing using Thunder Client

We can also create a database entry to manage session timeout, tracking and termination features so that we can persist and validate login activity of a player without asking to authenticate every time the player loads the game application. But that'll be a future prospect for now.

Comments

Popular posts from this blog

Implement Authentication (in Unity) | Link and Unlink account using PlayerPrefs

In this blog post, we'll delve into the process of implementing authentication in Unity, along with user account linking and unlinking using PlayerPrefs. Let's break down each step, from setting up the UI canvas to managing player data effectively.

Creating and Hosting the Game Backend using Node.js in Render

This is the first development blog post in a series  for "Masters of Mischief".  This post specifically is about the development of a backend for our 3D multiplayer game.

How I Set Up GitHub Collaboration and CI/CD with GitHub Actions for our Unity Game Project

Transitioning to GitHub collaboration and CI/CD for "Masters of Mischief" was a game-changer. It all started with the frustration of the old-school ZIP file transfers among developers, waiting for one another to finish their tasks before diving in. That approach was inefficient, to say the least. So, we decided to bid farewell to that headache and revamp our workflow.