Authorization and Authentication in JavaScript (Node.js)
In modern web development, the security of user data is a top priority. In this guide, we will break down the key concepts of authentication (verifying identity) and authorization (access control) in the Node.js environment. You will learn how to implement registration, password login, use JWT tokens, and protect routes.
1. Basic Concepts
- Authentication — the process of confirming identity (e.g., via email+password).
- Authorization — checking whether a user has the right to perform an action (admin/user role).
- JWT (JSON Web Token) — a compact way to transmit data as a token, often used for sessions.
- Password Hashing — a mandatory security requirement (bcrypt, argon2).
2. Installing Dependencies
For this, we will need the following npm packages:
npm install express bcryptjs jsonwebtoken dotenvexpress— web frameworkbcryptjs— password hashingjsonwebtoken— creating and verifying JWTdotenv— managing secret keys
3. Simple Registration and Password Hashing
Let's create a basic user model (for the example, we'll use an in-memory array; in a real project, replace it with a database):
const bcrypt = require('bcryptjs');const users = []; // simulating a database
async function registerUser(email, password) { const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); users.push({ email, password: hashedPassword }); console.log('User registered:', email);}
// Example call:registerUser('user@example.com', 'myPassword123');4. Authentication with JWT
After a successful login, we issue a JWT token to the client. The token contains the user ID and an expiration time.
const jwt = require('jsonwebtoken');require('dotenv').config();
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
function loginUser(email, password) { const user = users.find(u => u.email === email); if (!user) return null;
const isValid = bcrypt.compareSync(password, user.password); if (!isValid) return null;
// Create the token const token = jwt.sign( { userId: user.email, role: 'user' }, JWT_SECRET, { expiresIn: '1h' } ); return token;}5. Middleware for Protecting Routes
Let's create middleware that checks the JWT in the Authorization header:
function authMiddleware(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) { return res.status(401).json({ message: 'Token not provided' }); }
try { const decoded = jwt.verify(token, JWT_SECRET); req.user = decoded; // pass user data to the request next(); } catch (err) { return res.status(403).json({ message: 'Invalid token' }); }}6. Example Usage in Express
Putting it all together — creating routes for login and a protected profile:
const express = require('express');const app = express();app.use(express.json());
// Login routeapp.post('/api/login', (req, res) => { const { email, password } = req.body; const token = loginUser(email, password); if (!token) { return res.status(401).json({ message: 'Invalid credentials' }); } res.json({ token });});
// Protected routeapp.get('/api/profile', authMiddleware, (req, res) => { res.json({ message: 'Access