Contents
Authentication and Security in Node.js
When building a web application, making sure users can securely log in and keeping sensitive information safe is crucial. This guide will walk you through the basics of authentication in Node.js, how to set up user authentication with Passport.js, securing your app with environment variables and bcrypt, and using JSON Web Tokens (JWT) for authentication.
Understanding Authentication in Node.js
Authentication is all about verifying who a user is. In a web app, this usually means the user provides a username and password, and you check these against what’s stored in your system.
There are a few common ways to handle authentication:
- Session-Based Authentication: The server creates a session for the user and stores the session ID in a cookie. This session ID is used to track the user’s requests.
- Token-Based Authentication: The server gives the user a token (like a JWT) after they log in. This token is stored on the client side and sent with every request to confirm the user’s identity.
- OAuth and OpenID Connect: These are standard protocols that allow users to log in with third-party services like Google or Facebook.
Setting Up User Authentication with Passport.js
Passport.js is a popular tool in Node.js for handling user authentication. It supports various strategies, like logging in with a username/password, OAuth, and more.
- 1. Install Passport.js and Dependencies
First, you need to install Passport.js along with the local strategy for handling username/password authentication.
npm install passport passport-local express-session
- 2. Set Up Passport.js in Your App
Configure Passport.js to use a local strategy and manage user sessions.
const express = require('express');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const session = require('express-session');
const bcrypt = require('bcrypt');
// Mock user database
const users = [
{ id: 1, username: 'user1', passwordHash: bcrypt.hashSync('password1', 10) },
{ id: 2, username: 'user2', passwordHash: bcrypt.hashSync('password2', 10) }
];
// Passport local strategy
passport.use(new LocalStrategy((username, password, done) => {
const user = users.find(u => u.username === username);
if (!user) return done(null, false, { message: 'Incorrect username.' });
if (!bcrypt.compareSync(password, user.passwordHash)) return done(null, false, { message: 'Incorrect password.' });
return done(null, user);
}));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
const user = users.find(u => u.id === id);
done(null, user);
});
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
// Routes
app.post('/login', passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
}));
app.get('/dashboard', (req, res) => {
if (req.isAuthenticated()) res.send('Welcome to your dashboard!');
else res.redirect('/login');
});
app.get('/login', (req, res) => {
res.send(' ');
});
app.get('/logout', (req, res) => {
req.logout();
res.redirect('/login');
});
app.listen(3000, () => console.log(`Server running on http://localhost:3000`));
Securing Your Application with Environment Variables and bcrypt
Sensitive information, like database credentials or secret keys, shouldn’t be hardcoded in your app. Instead, store these in environment variables.
1. Set Up Environment Variables
Use thedotenv
package to load environment variables from a.env
file.
npm install dotenv
Create a .env
file:
SECRET_KEY=your-secret-key
DB_USER=your-db-user
DB_PASS=your-db-pass
Load these variables in your app:
require('dotenv').config();
const secretKey = process.env.SECRET_KEY;
- 2. Use bcrypt for Password Hashing
Hash passwords before storing them to protect user data.
const bcrypt = require('bcrypt');
const saltRounds = 10;
const plainPassword = 'mysecretpassword';
bcrypt.hash(plainPassword, saltRounds, (err, hash) => {
if (err) throw err;
console.log('Hashed password:', hash);
});
To compare a password:
const enteredPassword = 'mysecretpassword';
const storedHash = 'stored-hashed-password-from-db';
bcrypt.compare(enteredPassword, storedHash, (err, result) => {
if (err) throw err;
console.log(result ? 'Password matches!' : 'Password does not match.');
});
Introduction to JWT (JSON Web Tokens) for Authentication
JWTs are a popular way to handle authentication in web apps. They’re compact, URL-safe tokens that represent user information.
1. Install the jsonwebtoken Package
npm install jsonwebtoken
- 2. Generate a JWT
When a user logs in, create a JWT and send it back to the client.
const jwt = require('jsonwebtoken');
const user = { id: 1, username: 'johndoe' };
const token = jwt.sign(user, 'your-secret-key', { expiresIn: '1h' });
console.log('Generated JWT:', token);
- 3. Verify a JWT
For protected routes, verify the JWT to ensure the user is authenticated.
function authenticateToken(req, res, next) {
const token = req.headers['authorization'];
if (!token) return res.sendStatus(401);
jwt.verify(token, 'your-secret-key', (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
app.get('/dashboard', authenticateToken, (req, res) => {
res.send('Welcome to the protected dashboard!');
});
Conclusion
Authentication and security are crucial for any web application. With Node.js, tools like Passport.js, bcrypt, environment variables, and JWTs give you the building blocks to create a secure, reliable authentication system. By mastering these techniques, you can keep your app and users’ data safe from threats.
Related Chapters
- What is Node.js?
- Setting Up the Development Environment
- Understanding the Basics
- Node.js Modules
- Working with the File System
- Node.js Package Manager (npm)
- Asynchronous Programming in Node.js
- Building a Web Server with Node.js
- Introduction to Express.js
- Working with Databases
- Authentication and Security
- RESTful APIs with Node.js
- Testing in Node.js
- Planning the Project
- Developing the Backend with Node.js
- Developing the Frontend
- Deployment