DEV Community

Giancarlo Ramirez
Giancarlo Ramirez

Posted on

Express & JWT demo server

Repo: https://github.com/zendostrike/express-jwt-demo-server

Hello, let's create a simple Express + JWT demo server you can use in your demo projects.

First of all, let's create a new directory for our project:
mkdir express-jwt-demo-server && cd express-jwt-demo-server

Init npm
npm init -y

Install express library.
npm install express

Install jsonwebtoken library.
npm install jsonwebtoken

Install sqlite3 library to save your users.
npm install sqlite3


Database

Let's create a database.js file and create a database and a Users table using sqlite3.

const sqlite3 = require('sqlite3');

const db = new sqlite3.Database('database.db');

db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    email TEXT NOT NULL,
    password TEXT NOT NULL,
    name TEXT,
    lastName TEXT
  )
`);

module.exports = {
  db
}
Enter fullscreen mode Exit fullscreen mode

Secret

Create a constants.js file to save the JWT secret. You can use any string as your secret taking into account that this only for demo purposes.

const secretKey = 'a1521a878991a0941572eafc7708c7cb00756dd8d6844dbb9cc294c74e2108dfa09df9140c0fff6bc6a1e35e8be4b5b4e7bf79b7470fbfaadbb37d61ec6afb6f';

module.exports = { secretKey }
Enter fullscreen mode Exit fullscreen mode

Middleware

Create a verify-token.js file. This is going to be our middleware in charge of verify token.

const jwt = require('jsonwebtoken');
const { secretKey } = require('../constants');

function verifyToken(req, res, next) {
  const token = req.headers.authorization;

  if (!token) {
    return res.status(401).json({ error: 'Unauthorized: No token provided' });
  }

  jwt.verify(token.split(' ')[1], secretKey, (err, decoded) => {
    if (err) {
      return res.status(401).json({ error: 'Unauthorized: Invalid token' });
    }

    // Store the decoded token data in the request for future use
    req.user = decoded;
    next();
  });
}

module.exports = {
  verifyToken
}
Enter fullscreen mode Exit fullscreen mode

Package.json scripts

Let's modify our package.json scripts to run our project (you can use --watch to hot reload the project when code is changed):

  ...
  "scripts": {
    "start": "node --watch index.js"
  },
  ...
Enter fullscreen mode Exit fullscreen mode

Express app

Create a index.js file importing our other files and create a new express app running at port 3000.

const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const { verifyToken } = require('./verify-token');
const { secretKey } = require('./constants');
const { db } = require('./database');

const app = express();
const port = 3000;

// Middleware for parsing JSON request bodies
app.use(bodyParser.json());

// Start the Express server
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Cool, if you run npm start you will see the server running.
Now we need some routes.

Create a Register route

  • It takes name, lastName, email and password to create a new user.
  • If email or password missing will return an error.
  • If email already used will return an error.
  • Attemps creating a new user, if fails return error, if success JWT creates a new token using user's information and the secret.
// Endpoint to register a new user and generate a JWT token
app.post('/register', (req, res) => {
  const { name, lastName, email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({ error: 'Email and password are required' });
  }

  // Check if the user with the same email already exists in the database
  db.get('SELECT * FROM users WHERE email = ?', [email], (err, existingUser) => {
    if (err) {
      return res.status(500).json({ error: 'Database error' });
    }

    if (existingUser) {
      return res.status(409).json({ error: 'Email already in use' });
    }

    // If the email is not already in use, proceed with user registration
    // Insert the new user into the database
    db.run(
      'INSERT INTO users (name, lastName, email, password) VALUES (?, ?, ?, ?)',
      [name, lastName, email, password],
      (err) => {
        if (err) {
          return res.status(500).json({ error: 'Error registering user' });
        }

        // Generate a JWT token for the registered user
        const token = jwt.sign({ name, lastName, email }, secretKey, { expiresIn: '1h' });

        res.status(201).json({ message: 'User registered successfully', token });
      }
    );
  });
});
Enter fullscreen mode Exit fullscreen mode

Create a Login Route

  • It will recieve email and password
  • If wrong email or password returns an error.
  • If correct user and password will create a token and returns it.
app.post('/login', (req, res) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({ error: 'Email and password are required' });
  }

  // Generate a JWT token for the logged-in user
  const token = jwt.sign({ email }, secretKey, { expiresIn: '1h' });

  res.status(200).json({ message: 'Login successful', token });
});
Enter fullscreen mode Exit fullscreen mode

Create a route for getting Logged User

It will all the information from the access token. You will have to add Bearer token to your request to get a correct response.

app.get('/user', verifyToken, (req, res) => {
  res.status(200).json(req.user);
});
Enter fullscreen mode Exit fullscreen mode

Finally create a protected route to test our token.

app.get('/protected', verifyToken, (_, res) => {
  // If the middleware (verifyToken) has passed, it means the token is valid
  res.status(200).json({ message: 'OK, you have a valid token.' });
});
Enter fullscreen mode Exit fullscreen mode

Now you can test your frontend project and build a sessions based on JWT access token.

Repo: https://github.com/zendostrike/express-jwt-demo-server

Top comments (0)