Learn how to implement secure authentication in your web app using React and Express. Step-by-step guide with tips, code samples, and best practices.
Table of content
Authentication is a cornerstone of modern web applications. When building a full-stack app with React (for the frontend) and Express (for the backend), securing user data and ensuring safe user sessions is just as important as delivering great features. In this article, we’ll walk you through how to implement authentication in a typical React and Express setup, complete with code examples and best practices.
Two popular strategies for authentication with React and Express are:
npm install express bcryptjs jsonwebtoken cors
const users = []; // Replace with a proper database in production
const express = require('express');
const bcrypt = require('bcryptjs');
const router = express.Router();
router.post('/register', async (req, res) => {
const { username, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
users.push({ username, password: hashedPassword });
res.status(201).send('User registered!');
});
const jwt = require('jsonwebtoken');
router.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(400).send('Invalid credentials');
}
const token = jwt.sign({ username }, 'your_jwt_secret', { expiresIn: '1h' });
res.json({ token });
});
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, 'your_jwt_secret', (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
router.get('/profile', authenticateToken, (req, res) => {
res.json({ message: `Welcome, ${req.user.username}` });
});
npm install axios
import React, { useState } from 'react';
import axios from 'axios';
function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [token, setToken] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
try {
const res = await axios.post('http://localhost:5000/login', { username, password });
setToken(res.data.token);
localStorage.setItem('token', res.data.token);
} catch {
alert('Login failed');
}
};
return (
<form onSubmit={handleSubmit}>
<input value={username} onChange={e => setUsername(e.target.value)} placeholder="Username" />
<input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="Password" />
<button type="submit">Login</button>
</form>
);
}
export default Login;
async function getProfile() {
const token = localStorage.getItem('token');
const res = await axios.get('http://localhost:5000/profile', {
headers: { 'Authorization': `Bearer ${token}` },
});
console.log(res.data);
}
localStorage
for highly sensitive apps – consider HTTPOnly cookies for added security.By combining React on the front end and Express on the back end, implementing authentication is both robust and flexible. With these examples and best practices, you’re well on your way to securing your full-stack applications. If you’re building a project for fulldev.pl or any other platform, following these guidelines will help create safe and user-friendly web applications.