To create an authentication system using React.js on the frontend, Express.js on the backend we need to implement the following:
Let's start with the backend to handle user authentication and token generation.
npm install express bcryptjs jsonwebtoken cors
Create an authController.js file to handle authentication logic:
// authController.js const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); // Mock user data (in production, you would use a real database) const users = [ { id: 1, username: 'john', password: '$2a$10$O1s8iLKRLPbPqhc1uTquLO.xODTC1U/Z8xGoEDU6/Dc0PAQ3MkCKy', // hashed password for 'password123' }, ]; // JWT Secret const JWT_SECRET = 'supersecretkey'; exports.login = (req, res) => { const { username, password } = req.body; const user = users.find((u) => u.username === username); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } bcrypt.compare(password, user.password, (err, isMatch) => { if (isMatch) { // Create a token const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '1h' }); return res.json({ token }); } else { return res.status(401).json({ error: 'Invalid credentials' }); } }); }; exports.validateToken = (req, res) => { const token = req.header('Authorization').replace('Bearer ', ''); if (!token) { return res.status(401).json({ error: 'No token provided' }); } try { const decoded = jwt.verify(token, JWT_SECRET); res.json({ user: { id: decoded.id, username: decoded.username } }); } catch (err) { res.status(401).json({ error: 'Invalid token' }); } };
Next, create the main server.js file for setting up Express:
// server.js const express = require('express'); const cors = require('cors'); const { login, validateToken } = require('./authController'); const app = express(); app.use(express.json()); app.use(cors()); // Authentication routes app.post('/api/login', login); app.get('/api/validate', validateToken); // Start the server const PORT = 5000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
Now let's set up the frontend using React.js and Pulsy to handle the authentication state.
npm install axios pulsy
We will create a Pulsy store to manage authentication state globally.
// authStore.js import { createStore, addMiddleware } from 'pulsy'; import axios from 'axios'; // Create a store to hold the user and token createStore('auth', { user: null, token: null, }, { persist: true }); // Persist the auth state in localStorage // Middleware to add Authorization header for authenticated requests addMiddleware('auth', (nextValue, prevValue, storeName) => { if (nextValue.token) { axios.defaults.headers.common['Authorization'] = `Bearer ${nextValue.token}`; } else { delete axios.defaults.headers.common['Authorization']; } return nextValue; });
This store will persist the authentication state (user and token) and automatically apply the Authorization header for authenticated requests.
Create helper functions to handle login and validation requests:
// authService.js import { setStoreValue } from 'pulsy'; import axios from 'axios'; const API_URL = 'http://localhost:5000/api'; export const login = async (username, password) => { try { const response = await axios.post(`${API_URL}/login`, { username, password }); const { token } = response.data; // Set token and user info in Pulsy store setStoreValue('auth', { token, user: { username } }); return true; } catch (error) { console.error('Login failed', error); return false; } }; export const validateToken = async () => { try { const response = await axios.get(`${API_URL}/validate`); const user = response.data.user; // Update the store with the user info setStoreValue('auth', { user, token: localStorage.getItem('auth_token') }); return true; } catch (error) { console.error('Token validation failed', error); return false; } }; export const logout = () => { setStoreValue('auth', { user: null, token: null }); localStorage.removeItem('pulsy_auth'); };
Now let’s create the React components for login and authenticated views.
// Login.js import React, { useState } from 'react'; import { login } from './authService'; const Login = () => { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const handleLogin = async (e) => { e.preventDefault(); const success = await login(username, password); if (!success) { setError('Invalid credentials. Try again.'); } }; return ( <div> <h2>Login</h2> <form onSubmit={handleLogin}> <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" required /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" required /> <button type="submit">Login</button> </form> {error && <p style={{ color: 'red' }}>{error}</p>} </div> ); }; export default Login;
// Dashboard.js import React from 'react'; import { usePulsy } from 'pulsy'; import { logout } from './authService'; const Dashboard = () => { const [auth] = usePulsy('auth'); const handleLogout = () => { logout(); window.location.reload(); // Simple page refresh to redirect to login }; return ( <div> <h2>Welcome, {auth.user.username}!</h2> <button onClick={handleLogout}>Logout</button> </div> ); }; export default Dashboard;
In the App.js component, you’ll want to check if the user is authenticated and conditionally render either the login or dashboard.
// App.js import React, { useEffect } from 'react'; import { usePulsy } from 'pulsy'; import { validateToken } from './authService'; import Login from './Login'; import Dashboard from './Dashboard'; function App() { const [auth] = usePulsy('auth'); useEffect(() => { // Check token validity on app load if (auth.token) { validateToken(); } }, [auth.token]); return ( <div className="App"> {auth.user ? <Dashboard /> : <Login />} </div> ); } export default App;
Now that we have both the backend and frontend set up, you can run the application.
node server.js
npm start
Once both are running:
This example shows how to integrate Pulsy with a React authentication system backed by an Express.js API. Pulsy helps you manage global state for authentication, including persistence of the authentication token and user data across sessions, making it a powerful and easy-to-use state management tool.
The above is the detailed content of Authentication with express js and react js unsing jwt. For more information, please follow other related articles on the PHP Chinese website!