In this tutorial, we will go through how to create a JWT authentication system using Node.js, Express.js, and PostgreSQL. Let's get started.
Technologies Used
Prerequisites
- Node.js installed
- Postman installed
- ElephantSQL Account
- PostgreSQL installed
- pgAdmin installed
Getting Started
To get started, create a folder where you want to store your project. Open the folder in your favorite code editor. I will be using VS Code.
In the terminal, run the following command to create a package.json file.
npm init -y
This will create a package.json file in your project folder. The -y flag will accept all the default values.
Installing Dependencies
We will be using the following dependencies in this tutorial.
npm install express pg jsonwebtoken bcryptjs cors dotenv
Creating the Project
create a file named app.js and add the following code.
//app.js
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello world');
});
app.listen(8000, () => {
console.log('Server is running on port 8000');
});
module.exports = app;
In the terminal, run the following command to start the server.
node app.js
Open your browser and go to http://localhost:8000. You should see Hello world.
Database
We will be using ElephantSQL to create our database. Create an account on ElephantSQL and create a new database.
Create a Table
open up pgAdmin and connect to your database. Then create a new table named users. The table should have the following columns.
- id
- name
- username
- password
Creating the Database Connection
Create a file named db.js in the root folder and add the following code. You can get your database connection string from ElephantSQL.
//db.js
const { Client } = require('pg');
require('dotenv').config();
const client = new Client(`${process.env.DATABASE_URL}`);
module.exports = client;
Connecting to your database
In the app.js file, add the following code.
//app.js
const express = require('express');
const cors = require('cors');
const app = express();
const client = require('./db');
const PORT = process.env.PORT || 5000;
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello world');
});
app.listen(PORT, async () => {
try {
await client.connect();
console.log('Connected to database');
console.log(`Server is running on port ${PORT}`);
} catch (error) {
console.error(error);
}
});
then run the following command in the terminal.
node app.js
You should see Connected to database in the terminal and Server is running on port 5000.
Creating The Routes
Create a folder named routes and create a file named auth.js. Add the following code.
In the auth.js file, add the following code.
//routes/auth.js
const express = require('express');
const router = express.Router();
const controllers = require('../controllers/auth');
router.post('/register', controllers.register);
router.post('/login', controllers.login);
module.exports = router;
Create a folder named controllers and create a file named auth.js. Add the following code.
//controllers/auth.js
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const client = require('../db');
const register = async (req, res) => {
try {
const { name, username, password } = req.body;
// Hash the password
const hashedPassword = await bcrypt.hash(password, 10);
//create user
const response = await client.query(
'INSERT INTO users (name, username, password) VALUES ($1, $2, $3) RETURNING *',
[name, username, hashedPassword]
);
const accessToken = jwt.sign(
{ username: response.rows[0].username },
process.env.ACCESS_TOKEN_SECRET
);
res.status(200).json({
auth: true,
token: `Bearer ${accessToken}`,
});
} catch (error) {
console.error(error);
res.status(500).send('Server Error');
}
};
Also, add the following code to the auth.js file.
//controllers/auth.js
const login = async (req, res) => {
try {
const { username, password } = req.body;
const response = await client.query(
'SELECT * FROM users WHERE username = $1',
[username]
);
if (response.rows.length === 0) {
return res.status(400).json({
auth: false,
message: 'User not found',
});
}
const user = response.rows[0];
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
return res.status(400).json({
auth: false,
message: 'Invalid password',
});
}
const accessToken = jwt.sign(
{ username: user.username },
process.env.ACCESS_TOKEN_SECRET
);
res.status(200).json({
auth: true,
message: 'User logged in',
token: `Bearer ${accessToken}`,
});
} catch (error) {
console.error(error);
res.status(500).send('Server Error');
}
};
Then verify the user in the auth.js file.
//controllers/auth.js
const verifyAuthToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (token == null) {
return res.sendStatus(401);
}
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if (err) {
return res.sendStatus(403);
}
req.user = user;
next();
});
};
module.exports = {
register,
login,
verifyAuthToken,
};
Now lets update our app.js file, add the following code.
//app.js
const express = require('express');
const cors = require('cors');
const app = express();
const client = require('./db');
const PORT = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
app.use('/auth', require('./routes/auth'));
app.get('/', (req, res) => {
res.send('Hello world');
});
app.listen(PORT, async () => {
try {
await client.connect();
console.log('Connected to database');
console.log(`Server is running on port ${PORT}`);
} catch (error) {
console.error(error);
}
});
In the terminal, run the following command to start the server.
node app.js
Open Postman and send a POST request with name, username, password in the body to http://localhost:5000/auth/register. You should see the following response.
{
"auth": true,
"token": "Bearer [token]"
}
Open Postman and send a POST request with username, password, and the token from above in the body to http://localhost:5000/auth/login. You should see the following response.
{
"auth": true,
"token": "Bearer [token]"
}
🎉 Congratulations!
You have successfully created a login and register system using Node.js, Express, and PostgreSQL.
Conclusion
In this tutorial, we created a simple authentication system using Node.js, Express, and PostgreSQL. We used JWT for authentication and bcrypt for hashing passwords.