Login functionality using PERN
To implement a login functionality using React for the front-end, Node.js for the back-end, and Sequelize as the ORM (Object Relational Mapping) for interacting with a database (like PostgreSQL or MySQL), you can break down the process into several steps,
Set up the Project Structure
You'll need to create a full-stack application with separate folders for the client (React) and the server (Node.js with Sequelize)./project-root /client # React front-end /server # Node.js back-end with Sequelize
Server-side Implementation
i) Install dependencies
First, you'll need to install the necessary packages for your Node.js server.npm init -y npm install express # Web framework for Node.js npm install sequelize sequelize-cli # ORM for database interaction npm install mysql2 npm install bcryptjs # For password hashing npm install jsonwebtoken # For creating and verifying JWTs (JSON Web Tokens) npm install cors # Middleware to handle CORS (Cross-Origin Resource Sharing) npm install dotenv # To manage environment variables
ii) Sequelize Setup
Run the following commands to set up Sequelize and create your models.npx sequelize-cli init npx sequelize-cli model:generate --name User --attributes username:string,email:string,password:string npx sequelize-cli db:migrate
This will create the Sequelize config, models, and migrations for the
User
model with the fieldsusername
,email
, andpassword
.
iii) Create Express Server
Create anindex.js
orapp.js
file in theserver
folder to set up the Express server.const express = require('express'); const cors = require('cors'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const { User } = require('./models'); // Import the User model require('dotenv').config(); const app = express(); app.use(express.json()); app.use(cors()); const PORT = process.env.PORT || 5000; const JWT_SECRET = process.env.JWT_SECRET || 'supersecretkey'; // User Registration app.post('/register', async (req, res) => { const { username, email, password } = req.body; try { // Hash the password const hashedPassword = await bcrypt.hash(password, 10); // Create a new user const user = await User.create({ username, email, password: hashedPassword }); res.status(201).json(user); } catch (error) { res.status(500).json({ error: 'Error registering user' }); } }); // User Login app.post('/login', async (req, res) => { const { email, password } = req.body; try { // Check if user exists const user = await User.findOne({ where: { email } }); if (!user) { return res.status(400).json({ error: 'Invalid email or password' }); } // Compare the provided password with the stored hashed password const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) { return res.status(400).json({ error: 'Invalid email or password' }); } // Generate JWT token const token = jwt.sign({ id: user.id, email: user.email }, JWT_SECRET, { expiresIn: '1h', }); res.json({ token }); } catch (error) { res.status(500).json({ error: 'Error logging in' }); } }); // Protected Route (example) app.get('/profile', authenticateToken, (req, res) => { res.json({ message: 'This is a protected route', user: req.user }); }); // Middleware for Token Authentication function authenticateToken(req, res, next) { const token = req.headers['authorization']; if (!token) return res.status(401).json({ error: 'Access Denied' }); jwt.verify(token, JWT_SECRET, (err, user) => { if (err) return res.status(403).json({ error: 'Invalid Token' }); req.user = user; next(); }); } app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
iv) Environment Variables
Create a.env
file to store sensitive information like JWT secret and database credentials.JWT_SECRET=supersecretkey
Client-side Implementation
i) Install dependencies
Inside theclient
folder, create a React project and install the required dependencies.npx create-react-app client cd client npm install axios # To make HTTP requests to the back-end npm install react-router-dom # To handle routing between different pages in React
ii) Create the Login and Registration Forms
In your React app, createLogin.js
andRegister.js
components to handle user login and registration.// src/Register.js import { useState } from 'react'; import axios from 'axios'; function Register() { const [username, setUsername] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleRegister = async (e) => { e.preventDefault(); try { const response = await axios.post('http://localhost:5000/register', { username, email, password }); console.log(response.data); } catch (error) { console.error('Error registering user', error); } }; return ( <div> <h2>Register</h2> <form onSubmit={handleRegister}> <input type="text" placeholder="Username" onChange={(e) => setUsername(e.target.value)} /> <input type="email" placeholder="Email" onChange={(e) => setEmail(e.target.value)} /> <input type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Register</button> </form> </div> ); } export default Register;
// src/Login.js import { useState } from 'react'; import axios from 'axios'; function Login() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [token, setToken] = useState(''); const handleLogin = async (e) => { e.preventDefault(); try { const response = await axios.post('http://localhost:5000/login', { email, password }); setToken(response.data.token); // Store token in state } catch (error) { console.error('Error logging in', error); } }; return ( <div> <h2>Login</h2> <form onSubmit={handleLogin}> <input type="email" placeholder="Email" onChange={(e) => setEmail(e.target.value)} /> <input type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Login</button> </form> {token && <p>Your token: {token}</p>} </div> ); } export default Login;
iii) Protect Routes in React
You can create a higher-order component to protect certain routes in React using the JWT token.
// src/PrivateRoute.js import { Route, Redirect } from 'react-router-dom'; const PrivateRoute = ({ component: Component, ...rest }) => { const isAuthenticated = !!localStorage.getItem('token'); return ( <Route {...rest} render={props => isAuthenticated ? ( <Component {...props} /> ) : ( <Redirect to="/login" /> ) } /> ); }; export default PrivateRoute;
Connecting Front-end with Back-end
i) Ensure the React app is running on a different port (e.g., 3000) and that CORS is handled in the Node.js server (already included in the setup with
cors()
).ii) Use
axios
to make HTTP requests from the React components to the back-end API endpoints (/register
and/login
).Running the Application
i) Run the back-end servercd server node app.js
ii) Run the React front-end
cd client npm start
With this setup, you have a basic login and registration system using React, Node.js, and Sequelize. You can further extend it by adding features such as validation, error handling, and session management.