Press ESC to close

How to Authenticate & Authorize Users in a Node.js Express App

User authentication and authorization are essential for building secure applications. Whether you’re an ERP Implementation Consultant or a developer crafting a scalable solution, understanding these concepts ensures your application is both functional and safe. This article will guide you through the steps to authenticate and authorize users in a Node.js Express application, complete with a custom code example.

1. Understanding Authentication vs. Authorization

Authentication and authorization, though related, serve distinct purposes:

  • Authentication: Confirms the identity of a user. For example, verifying an email and password.
  • Authorization: Determines what actions an authenticated user is allowed to perform within the application.

In simpler terms, authentication answers “Who are you?” while authorization answers “What can you do?” Combining both ensures that only legitimate users gain access and that they can only interact with resources they’re permitted to.

2. Setting Up the Environment

To start, make sure you have the following tools ready:

  1. Node.js: Install the latest stable version from Node.js.
  2. Express: A minimal framework for building Node.js applications.
  3. npm: Node’s package manager to install required dependencies.

Run the following commands in your terminal to initialize a project:

mkdir auth-app && cd auth-app

npm init -y

npm install express bcryptjs jsonwebtoken dotenv

Here’s a quick breakdown:

  • express: Framework to handle routing.
  • bcryptjs: Library for hashing passwords.
  • jsonwebtoken: Tool for generating and verifying JSON Web Tokens (JWT).
  • dotenv: Handles environment variables securely.

3. Hashing Passwords

Storing passwords in plain text is a critical security flaw. Use bcryptjs to hash passwords before saving them.

const bcrypt = require(‘bcryptjs’);

 

const hashPassword = async (password) => {

  const salt = await bcrypt.genSalt(10);

  const hashedPassword = await bcrypt.hash(password, salt);

  return hashedPassword;

};

 

// Example usage

hashPassword(‘myPlainTextPassword’)

  .then((hashed) => console.log(`Hashed Password: ${hashed}`))

  .catch((err) => console.error(err));

In the code above, bcryptjs adds an extra layer of security by salting the password, making it more resilient against brute force attacks.

4. Authenticating Users

Authentication involves validating user credentials. Here’s how to implement login functionality:

const express = require(‘express’);

const bcrypt = require(‘bcryptjs’);

const jwt = require(‘jsonwebtoken’);

 

const app = express();

app.use(express.json());

 

const users = [

  { id: 1, username: ‘testUser’, password: ‘$2a$10$somethinghashed’ }, // Example hashed password

];

 

app.post(‘/login’, async (req, res) => {

  const { username, password } = req.body;

  const user = users.find((u) => u.username === username);

  if (!user) return res.status(400).json({ message: ‘Invalid username or password.’ });

 

  const isMatch = await bcrypt.compare(password, user.password);

  if (!isMatch) return res.status(400).json({ message: ‘Invalid username or password.’ });

 

  const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: ‘1h’ });

  res.json({ token });

});

 

app.listen(3000, () => console.log(‘Server running on port 3000’));

In this code:

  • A JWT is generated upon successful login.
  • Replace process.env.JWT_SECRET with a secure string stored in your .env file.

5. Authorizing User Actions

Authorization ensures only permitted actions are executed. Middleware is the perfect place to implement this:

const authenticateToken = (req, res, next) => {

  const token = req.header(‘Authorization’);

  if (!token) return res.status(401).json({ message: ‘Access denied.’ });

 

  try {

    const verified = jwt.verify(token, process.env.JWT_SECRET);

    req.user = verified;

    next();

  } catch (err) {

    res.status(400).json({ message: ‘Invalid token.’ });

  }

};

 

app.get(‘/protected’, authenticateToken, (req, res) => {

  res.send(‘This is a protected route.’);

});

Here, the middleware checks for a valid token before allowing access to protected routes.

6. Custom Code: Combining Authentication and Authorization

Here’s how to combine both authentication and authorization for a role-based access system:

const authorizeRole = (role) => {

  return (req, res, next) => {

    if (req.user.role !== role) {

      return res.status(403).json({ message: ‘Forbidden’ });

    }

    next();

  };

};

 

// Example usage

app.get(‘/admin’, authenticateToken, authorizeRole(‘admin’), (req, res) => {

  res.send(‘Welcome Admin!’);

});

This snippet ensures only users with the specified role can access certain routes.

Conclusion

Implementing secure authentication and authorization is critical for any Node.js application. By hashing passwords, validating credentials, and protecting routes with middleware, you’ll significantly reduce security risks.

Need expert assistance with your Odoo or ERP projects? Contact us today to hire a skilled Odoo consultant and bring your vision to life!

Leave a Reply

Your email address will not be published. Required fields are marked *